2

可能重复:
使用带有 Xml 命名空间的 Linq to Xml

我有一个xml:

<?xml version="1.0" encoding="UTF-8"?>
<string xmlns="http://tempuri.org/">
<Global>
   <Items>
      <Item text="Main text" key="1">
         <Item text="Some text" key="1.1"/>
         <Item text="Other text" key="1.2"/>
         <Item text="Text" key="1.3"/>
      </Item>
      <Item text="Main text 2" key="2">
         <Item text="Some text" key="2.1"/>
         <Item text="Other text" key="2.2"/>
         <Item text="Text" key="2.3"/>
      </Item>
   </Items>
</Global>
</string>

我需要在 Item 中获取项目(例如使用键 2.1、1.1 等)。

我有这个代码:

var xml = GetXmlFromWeb(service.ServiceLink, true);
                var stringXml = new StringReader(xml); // Load data from web)
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.IgnoreWhitespace = true;
                var reader = XmlTextReader.Create(stringXml, settings);

                XDocument docWithDecode = XDocument.Load(reader);
                IEnumerable<XElement> elements = docWithDecode.Root.Descendants("Item");

结果我得到了Count = 0。

这很有趣,如果我写IEnumerable<XElement> elements = docWithDecode.Root.Descendants();了,我得到了元素,但是结构看起来很乱,数据被复制了,每个项目都有命名空间引用等。所以这里出了点问题。

有人可以帮我编写工作代码吗?谢谢!

4

3 回答 3

1
XNamespace ns = "http://tempuri.org/";
IEnumerable<XElement> elements = docWithDecode.Root.Descendants(ns+"Item");
于 2012-05-24T14:26:33.513 回答
1

正如我在评论中提到的和 LB 在他的回答中提到的那样,您的.Count()== 0 问题是由于缺少命名空间。请参阅我上面链接的这个答案以更详细地解释它,但实际上您的问题是您正在搜索一个名为“Item”的元素,但实际上您实际上想要找到的是命名空间 +“Item”。您只需要将命名空间添加到查询中。

重新阅读您的问题后,我注意到您的 XML 和查询存在问题。您有一个具有多个同名子节点的节点。如果您使用Descendants(),您将选择全部 8 个,而不是您在问题中指定的 6 个。

要仅选择子<Item>节点,您需要修改查询,因为Descendants()将选择任何匹配的内容。您实际上需要使用.Elements()扩展方法并具体选择每个级别。

XNamespace ns = "http://tempuri.org/";
IEnumerable<XElement> elements = docWithDecode.Root
                                              .Elements(ns + "Global")
                                              .Elements(ns + "Items")
                                              .Elements(ns + "Item")
                                              .Elements(ns + "Item");

您也可以使用Descendants(ns + "Items")而不是查询中的前 2 个Elements(),因为它不会在自身内部重复。

于 2012-05-24T14:34:41.747 回答
0

首先,不要使用Root.Descendants(),这将返回IEnumerable<XElement>所有孩子中的一个,并且不会保留树结构。它对所有 XElement 子项一视同仁,无论它们在树中的位置如何。您应该始终尝试使用Root.Elements(ns + "InnerElementName");,这也将返回一个IEnumerable<XElement>,但仅适用于 Root 的孩子,(而不是孙辈:))。

您收到 0 个元素 usingDescendants("Item")的原因是缺少命名空间。确保添加命名空间,如果 XML 中有命名空间,根据我的经验,不添加元素名称将无法使用。

此代码将以您提供的结构遍历 XML 文件:

XNamespace ns = docWithDecode.Root.Name.Namespace;
XElement xGlobal = docWithDecode.Root.Element(ns + "Global");
forach (XElement xItems in xGlobal.Elements(ns + "Items")
{
   XAttribute outerItemText = xItems.Attribute("text");
   XAttribute outerItemKey = xItems.Attribute("key");

   foreach (XElement xItem in xItems.Elements(ns + "Item"))
   {
      XAttribute innerItemText = xItem.Attribute("text");
      XAttribute innerItemKey = xItem.Attribute("key");
   }
}

我没有调试这个(我在这台计算机上没有 VS)所以告诉我它是否不起作用,但我想你会明白的。

于 2012-05-24T14:41:36.160 回答