如何使用两个名称空间查询XElement

时间:2012-06-27 15:22:35

标签: c# linq linq-to-xml xml-namespaces

我正在尝试使用LINQ-to-XML(XElement对象)查找元素的内部文本值。我进行了服务调用并获得了一个XML响应,我已成功加载到XElement对象中。我想提取其中一个元素的内部文本 - 但是,每次我尝试这样做时,都会得到一个null结果。

我觉得我错过了一些非常简单的东西,但我对LINQ-to-XML相当新。任何帮助表示赞赏。

我正在尝试获取StatusInfo / Status元素的内部文本值。这是我的XML文档:

<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">My Response</title>
  <id>tag:foo.com,2012:/bar/06468dfc-32f7-4650-b765-608f2b852f22</id>
  <author>
    <name>My Web Services</name>
  </author>
  <link rel="self" type="application/atom+xml" href="http://myServer/service.svc/myPath" />
  <generator uri="http://myServer" version="1">My Web Services</generator>
  <entry>
    <id>tag:foo.com,2012:/my-web-services</id>
    <title type="text" />
    <updated>2012-06-27T14:22:42Z</updated>
    <category term="tag:foo.com,2008/my/schemas#system" scheme="tag:foo.com,2008/my/schemas#type" />
    <content type="application/vnd.my.webservices+xml">
      <StatusInfo xmlns="tag:foo.com,2008:/my/data">
        <Status>Available</Status>  <!-- I want the inner text -->
      </StatusInfo>
    </content>
  </entry>
</feed>

这是我用来提取值的代码片段(不起作用):

    XElement root = XElement.Load(responseReader);
    XNamespace tag = "tag:foo.com,2008:/my/data";
    var status = (from s in root.Elements(tag + "Status")
                 select s).FirstOrDefault();

我的status变量始终为null。我已经尝试了几种变体,但无济于事。令我困惑的部分是命名空间 - tag2008已定义。我不知道我是否正确处理这个问题,或者是否有更好的方法来解决这个问题。

此外,我无法控制XML架构或XML的结构。我正在使用的服务不受我的控制。

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

尝试使用Descendants()代替Elements()

XElement x = XElement.Load(responseReader);
XNamespace ns = "tag:foo.com,2008:/my/data";
var status = x.Descendants(ns + "Status").FirstOrDefault().Value;

答案 1 :(得分:0)

Feed中有2个命名空间:

  1. Atom命名空间
  2. 标记名称空间
  3. 外部xml需要使用Atom命名空间,而内部xml的一部分需要使用标记命名空间。即,

    var doc = XDocument.Load(responseReader);
    XNamespace nsAtom = "http://www.w3.org/2005/Atom";
    XNamespace nsTag = "tag:foo.com,2008:/my/data";
    
    // get all entry nodes / use the atom namespace
    var entry = doc.Root.Elements(nsAtom + "entry");
    
    // get all StatusInfo elements / use the atom namespace
    var statusInfo = entry.Descendants(nsTag + "StatusInfo");
    
    // get all Status / use the tag namespace
    var status = statusInfo.Elements(nsTag + "Status");
    
    // get value of all Status
    var values = status.Select(x => x.Value.ToString()).ToList();