如何使用LINQ统计XML中含指定标签且对应字段值为Yes的Row数量?
Great question! Dealing with XML that has repeating, un-named <Dataset> and <Row> tags can feel tricky at first, but LINQ to XML makes it straightforward once you break down the logic. Let’s start with a sample XML structure that matches your scenario to make examples concrete:
<Root> <Dataset> <Row> <CustomerID>1</CustomerID> <IsActive>Yes</IsActive> <Email>john@example.com</Email> </Row> <Row> <CustomerID>2</CustomerID> <IsActive>No</IsActive> <Email>jane@example.com</Email> </Row> </Dataset> <Dataset> <Row> <CustomerID>3</CustomerID> <IsActive>Yes</IsActive> <!-- No Email tag here --> </Row> <Row> <CustomerID>4</CustomerID> <IsActive>Yes</IsActive> <Email>bob@example.com</Email> </Row> </Dataset> </Root>
1. Counting Rows That Meet Your Conditions
To count <Row> elements that:
- Contain a specified tag (e.g.,
<Email>) - Have another tag (e.g.,
<IsActive>) with the value "Yes"
Here’s the LINQ to XML code to handle this:
// Load your XML document (replace with your file path or in-memory string) XDocument doc = XDocument.Load("your-xml-file.xml"); // Define your target tags and validation value string requiredTag = "Email"; string validationTag = "IsActive"; string validationValue = "Yes"; // Calculate the count of matching rows int matchingRowsCount = doc.Descendants("Row") .Where(row => // Check if the row contains the required tag row.Elements(requiredTag).Any() && // Ensure the validation tag exists before accessing its value row.Elements(validationTag).Any() && // Verify the validation tag's value matches (case-insensitive for flexibility) row.Element(validationTag).Value.Equals(validationValue, StringComparison.OrdinalIgnoreCase) ) .Count(); Console.WriteLine($"Number of matching rows: {matchingRowsCount}");
Breakdown of the Query:
doc.Descendants("Row"): Grabs all<Row>elements anywhere in the XML, regardless of how deep they are nested under<Dataset>tags.row.Elements(requiredTag).Any(): Checks if the row has at least one instance of your specified tag (avoids trying to validate rows that don’t have the field you care about).row.Elements(validationTag).Any(): Prevents null reference errors by ensuring the validation tag exists before we check its value.StringComparison.OrdinalIgnoreCase: Makes the value check flexible (so "YES" or "yes" will also count as valid).
In our sample XML, this would return 2 (rows 1 and 4 meet both conditions).
2. Checking Individual Rows for Field Existence and Validation
If you need to validate rows one-by-one (e.g., during iteration), wrap the logic in a reusable method for clarity:
bool DoesRowMeetConditions(XElement row, string requiredTag, string validationTag, string validationValue) { // First, confirm the required tag exists if (!row.Elements(requiredTag).Any()) return false; // Then check the validation tag's value (if it exists) var validationElement = row.Element(validationTag); return validationElement != null && validationElement.Value.Equals(validationValue, StringComparison.OrdinalIgnoreCase); }
Usage Example:
// Loop through all rows and validate each one foreach (var row in doc.Descendants("Row")) { bool isValid = DoesRowMeetConditions(row, "Email", "IsActive", "Yes"); string customerId = row.Element("CustomerID")?.Value ?? "Unknown"; Console.WriteLine($"Row with CustomerID {customerId} is valid: {isValid}"); }
Key Edge Cases to Consider:
- XML Namespaces: If your XML uses namespaces, you’ll need to include them when referencing elements (e.g.,
XNamespace ns = "http://your-namespace-url"; row.Elements(ns + requiredTag)). - Missing Elements: Always check for element existence before accessing
Valueto avoidNullReferenceException. - Multiple Instances of a Tag: If a row can have multiple copies of the same tag, adjust the logic (e.g., use
row.Elements(requiredTag).All(...)if all instances need to meet a condition).
内容的提问来源于stack exchange,提问作者Stephen Archbold
相关产品推荐
相关产品推荐

