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

コメントで述べたように、彼の回答で LB が言及されているように、.Count()== 0 の問題は名前空間がないことが原因です。詳細を説明するために上記でリンクしたこの回答を参照してください。ただし、実際の問題は、「アイテム」という要素を検索していることですが、実際に見つけようとしているのは名前空間 + 「アイテム」です。名前空間をクエリに追加するだけです。

質問を読み直したところ、XML とクエリに問題があることに気付きました。同じ名前の複数の子ノードを持つノードがあります。を使用するDescendants()と、質問で指定した 6 つではなく、8 つすべてを選択することになります。

<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 に答える
1
XNamespace ns = "http://tempuri.org/";
IEnumerable<XElement> elements = docWithDecode.Root.Descendants(ns+"Item");
于 2012-05-24T14:26:33.513 に答える
0

まず、 を使用しないでくださいRoot.Descendants()。これはすべての子の を返しIEnumerable<XElement>、ツリー構造を保持しません。ツリー内の位置に関係なく、すべての XElement の子を同じように扱います。常に を使用してみてくださいRoot.Elements(ns + "InnerElementName");。これも を返しますIEnumerable<XElement>が、ルートの子に対してのみです (孫に対してではありません:))。

使用して 0 要素を受け取った理由Descendants("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 に答える