将LINQ XML与命名空间一起使用

时间:2014-08-18 00:25:24

标签: 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>

我的目标是使用以下代码提取节点值'Id':

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节点具有这些属性时获取值?

2 个答案:

答案 0 :(得分:3)

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的默认行为,如果没有给出明确的命名空间,则假设 no 名称空间。但是,XML规范的默认行为是假定父命名空间。在你的情况下,这两个是不同的,所以它无法找到后代。

答案 1 :(得分: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);