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

XDocument: How to find an attribute value in nested xml

鉴于下面的工作代码片段,我正在尝试获取 RootChild2 中的 target 元素。

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");
}

这里存在三个问题:

  • 您正在检查 RootChild2 元素是否有任何属性 - 但它没有
  • 您只检查每个 RootChild2 元素下的第一个 Child 元素
  • 假设 属性存在(通过取消引用 XAttribute

这里的代码将在 RootChild2:

中找到 all 个目标元素
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}");
    }            
}

请注意,将 XAttribute 转换为 string 是避免空引用问题的一种简单方法 - 因为当源为空时显式转换的结果为空。 (这是 LINQ to XML 中的一般模式。)

您正在通过循环内的 element 访问 RootChild2-Element 本身。 看看下面的版本:

        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");
        }

现在循环遍历 RootChild2 的所有节点。

您应该稍微重写 foreach 循环,在 RootChild2 中添加子 Elements() 集合的访问并检查枚举中的每个元素。您还可以检查元素中是否存在 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 仅具有匹配名称的元素,因此您在代码

中只会得到一个 RootChild2 元素作为结果

这会找到所有 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");
        }