将 LINQ XML 与命名空间结合使用

Dan*_*ith 4 c# xml linq

我正在尝试在 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>
Run Code Online (Sandbox Code Playgroud)

我的目标是使用如下代码提取节点值“Id”:

XDocument doc = XDocument.Load(filePath);
List<string> urlList = doc.Root.Descendants("Id")
                          .Select(x => (string)x)
                          .ToList();
Console.WriteLine(urlList.Count);
Run Code Online (Sandbox Code Playgroud)

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

经过一些调试和编辑 XML 后,我注意到如果我更改节点TrainingCenterDatabase并删除以下属性:

<TrainingCenterDatabase>
Run Code Online (Sandbox Code Playgroud)

那么结果就是预期的计数为 1。

所以我的问题是如何考虑命名空间,以便在节点TrainingCenterDatabase具有这些属性时可以获得值?

Mat*_*gen 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);
Run Code Online (Sandbox Code Playgroud)

基本上,这只是假设底层元素与根元素具有相同的命名空间。在本例中确实如此,但当然不一定如此。

正确的方法可能是明确地做到这一点。现在,当然,这取决于你如何使用它和你的数据源,所以你自己做出决定,但这需要做更多类似这样的事情:

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);
Run Code Online (Sandbox Code Playgroud)

问题的原因是,XElement当没有给出显式名称空间时, 的默认行为是假设没有名称空间。但是,XML 规范的默认行为是采用父级的命名空间。就您而言,这两个不同,因此无法找到后代。