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");
}
鉴于下面的工作代码片段,我正在尝试获取 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
:
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");
}