简体   繁体   English

结合使用LINQ XML和名称空间

[英]Use LINQ XML with a namespace

I am trying to find nodes in an XML document like this: 我试图在这样的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>

I aim to extract the node value 'Id' with code like this: 我的目标是使用如下代码提取节点值“ Id”:

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

However the count is 0, where I expect 1. 但是计数是0,我期望是1。

After some debugging and editing the XML I noticed that if I change the TrainingCenterDatabase node and remove the attributes to this: 经过一些调试和编辑XML之后,我注意到,如果我更改了TrainingCenterDatabase节点并删除了该属性,请执行以下操作:

<TrainingCenterDatabase>

Then the result is a count of 1 as expected. 然后结果是预期的1计数。

So my question is how do I take into account the namespaces so that I can get the value when the TrainingCenterDatabase node has these attributes? 所以我的问题是我如何考虑名称空间,以便在TrainingCenterDatabase节点具有这些属性时可以获取值?

Namespaces in XML can be tricky. XML中的命名空间可能很棘手。 I've run into this problem myself a number of times. 我已经多次遇到这个问题。 In all likelihood, the following will fix your problem: 很有可能,以下方法可以解决您的问题:

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

Basically, this just assumes the underlying element to have the same namespace as your root element. 基本上,这只是假设基础元素具有与根元素相同的名称空间。 That's true in this case, but of course it doesn't have to be. 在这种情况下是正确的,但是当然不必如此。

The right way, probably, is to do it explicitly. 正确的方法可能是显式地执行此操作。 Now, granted, that kind of depends on how you're using this and your datasource, so make the decision for yourself, but that would require doing something more like this: 现在,这取决于您如何使用此功能和数据源,因此请自己做出决定,但这需要做更多类似的事情:

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

The cause for your problem was that the default behavior for XElement , when not given an explicit namespace, is to assume no namespace. 问题的原因是XElement的默认行为(在未指定显式命名空间的情况下)假定没有命名空间。 However, the default behavior for the XML spec is to assume the parent's namespace. 但是,XML规范的默认行为是采用父级的名称空间。 In your case, those two were different, so it wasn't able to find the descendant. 在您的情况下,这两个是不同的,因此无法找到后代。

It Works... 有用...

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM