简体   繁体   English

XDocument:如何在嵌套的 xml 中查找属性值

[英]XDocument: How to find an attribute value in nested xml

Given the working code snippet below, I'm trying to get the target element inside RootChild2 .鉴于下面的工作代码片段,我试图在RootChild2获取target元素。

https://dotnetfiddle.net/eN4xV9 https://dotnetfiddle.net/eN4xV9

string str =
    @"<?xml version=""1.0""?>  
    <!-- comment at the root level -->  
    <Root>  
        <RootChild1>
            <Child>Content</Child>  
            <Child>Content</Child>  
            <Child>Content</Child>  
        </RootChild1>
        <RootChild2>
            <Child>Content</Child>  
            <Child key='target'>Content</Child>  
            <Child>Content</Child>  
        </RootChild2>
    </Root>";
XDocument doc = XDocument.Parse(str);

foreach (XElement element in doc.Descendants("RootChild2"))
{
    if (element.HasAttributes && element.Element("Child").Attribute("key").Value == "target")
        Console.WriteLine("found it");
    else
        Console.WriteLine("not found");
}

This finds all 3 RootChild2/Child elements, then tests each in turn:这会找到所有 3 个RootChild2/Child元素,然后依次测试每个元素:

        foreach (XElement child in doc.Descendants("RootChild2").Elements("Child"))
        {
            if ((string)child.Attribute("key") == "target")
                Console.WriteLine("found it");
            else
                Console.WriteLine("not found");
        }

There are three problems here:这里存在三个问题:

  • You're checking if the RootChild2 element has any attributes - and it doesn't您正在检查RootChild2元素是否具有任何属性 - 但它没有
  • You're only checking the first Child element under each RootChild2 element您只检查每个RootChild2元素下的第一个Child元素
  • You're assuming the attribute is present (by dereferencing the XAttribute )假设该属性存在(通过取消引用XAttribute

Here's code which will find all the target elements within a RootChild2 :这是将在RootChild2查找所有目标元素的RootChild2

foreach (XElement element in doc.Descendants("RootChild2"))
{
    var targets = element
        .Elements("Child")
        .Where(child => (string) child.Attribute("key") == "target")
        .ToList();
    Console.WriteLine($"Found {targets.Count} targets");
    foreach (var target in targets)
    {
        Console.WriteLine($"Target content: {target.Value}");
    }            
}

Note that the cast of XAttribute to string is a simple way of avoiding null reference issues - because the result of the explicit conversion is null when the source is null.请注意,将XAttributestring是一种避免空引用问题的简单方法 - 因为当源为空时,显式转换的结果为空。 (That's a general pattern in LINQ to XML.) (这是 LINQ to XML 中的一般模式。)

You are accessing the RootChild2-Element itself through element inside your loop.您是通过访问RootChild2-元素本身element的循环中。 Take a look at the following version:看看下面的版本:

        foreach (XElement element in doc.Descendants("RootChild2").Nodes())
        {
            if (element.HasAttributes && element.Attribute("key").Value == "target")
                Console.WriteLine("found it");
            else
                Console.WriteLine("not found");
        }

Now it loops through all nodes of RootChild2.现在它循环遍历 RootChild2 的所有节点。

You should rewrite your foreach loop at little bit, add accessing of child Elements() collection in RootChild2 and check every element in enumeration.您应该稍微重写您的foreach循环,在RootChild2添加对 child Elements()集合的RootChild2并检查枚举中的每个元素。 You also can check that key attribute is present in element to prevent a potential null reference exception您还可以检查元素中是否存在key属性以防止潜在的空引用异常

foreach (XElement element in doc.Descendants("RootChild2").Elements())
{
    if (element.HasAttributes && element.Attribute("key")?.Value == "target")
        Console.WriteLine("found it");
    else
        Console.WriteLine("not found");
}

Descendants(XName) returns only elements with matching names, therefore you are getting only one RootChild2 element as the result in your code Descendants(XName)仅返回具有匹配名称的元素,因此您在代码中仅获得一个RootChild2元素作为结果

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM