使用带有命名空间的LINQ XML

4

我试图在这样的XML文档中查找节点:

<?xml version="1.0"?>
<TrainingCenterDatabase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2">
  <Activities>
    <Activity Sport="CyclingTransport">
      <Id>2014-07-08T15:28:14Z</Id>
    </Activity>
  </Activities>
</TrainingCenterDatabase>

我希望能够使用以下代码提取节点值 'Id':
```python ```
XDocument doc = XDocument.Load(filePath);
List<string> urlList = doc.Root.Descendants("Id")
                          .Select(x => (string)x)
                          .ToList();
Console.WriteLine(urlList.Count);

然而,计数是0,我期望的是1。

经过一些调试和编辑XML后,我注意到如果我更改 TrainingCenterDatabase 节点并删除属性,就会变成这样:

<TrainingCenterDatabase>

然后结果符合预期,计数为1。
我的问题是如何考虑命名空间,以便在TrainingCenterDatabase节点具有这些属性时获取值?

另一种方法是使用LocalName,它忽略命名空间:https://dev59.com/wXM_5IYBdhLWcg3w9oaG - AaronLS
2个回答

5

XML中的命名空间可能会让人感到棘手。我自己也遇到过这个问题很多次。很可能以下方法可以解决您的问题:

XDocument doc = XDocument.Load(filePath);
List<string> urlList = doc.Root.Descendants(doc.Root.Name.Namespace.GetName("Id"))
                          .Select(x => (string)x)
                          .ToList();
Console.WriteLine(urlList.Count);

基本上,这个假设底层元素具有与根元素相同的命名空间。在这种情况下是正确的,但当然不一定总是如此。

可能正确的方法是显式地进行操作。现在,当然这取决于您如何使用它以及您的数据源,所以请自行决定,但这需要执行类似于以下内容的操作:

XDocument doc = XDocument.Load(filePath);
List<string> urlList = doc.Root.Descendants(System.Xml.Linq.XName.Get("Id", "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"))
                          .Select(x => (string)x)
                          .ToList();
Console.WriteLine(urlList.Count);

你遇到问题的原因是,当没有给定显式命名空间时,默认行为是假定没有命名空间的XElement。然而,XML规范的默认行为是假定父级的命名空间。在你的情况下,这两者不同,因此它无法找到后代节点。

这个完美地解决了。所以在原始示例中,列表计数为0的原因是因为假定该元素与根元素没有相同的命名空间? - Dan Smith
1
@DanSmith 说得好,我没有真正解释错误在哪里。我编辑了我的答案。但是,基本上它正在查找一个没有名称空间和名称为“Id”的元素,这与你正在寻找的元素不符,后者有一个命名空间。 - Matthew Haugen

0

它运行正常...

        XDocument doc = XDocument.Load(filePath);
        XNamespace ns = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2";
        var root = doc.Descendants(ns + "Id").Select(x => x.Value).ToList();
        Console.WriteLine(root.Count);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接