web-dev-qa-db-ja.com

XDocumentで要素を見つけますか?

単純なXMLがあります

_<AllBands>
  <Band>
    <Beatles ID="1234" started="1962">greatest Band<![CDATA[lalala]]></Beatles>
    <Last>1</Last>
    <Salary>2</Salary>
  </Band>
  <Band>
    <Doors ID="222" started="1968">regular Band<![CDATA[lalala]]></Doors>
    <Last>1</Last>
    <Salary>2</Salary>
  </Band>
</AllBands>
_

しかしながら 、

「ドアバンド」にアクセスしてそのIDを変更する場合:

_  using (var stream = new StringReader(result))
            {
                XDocument xmlFile = XDocument.Load(stream);

                var query = from c in xmlFile.Elements("Band")

                            select c;
                             ...
_

query結果がありません

しかし

xmlFile.Elements().Elements("Band")と書くと、見つかります。

何が問題ですか ?

ルートからのフルパスが必要ですか?

もしそうなら、AllBandsを指定せずに動作したのはなぜですか?

XDocumentナビゲーションでは、必要な要素までの完全なレベルの構造を知る必要がありますか?

49
Royi Namir

Elements()は直接の子のみをチェックします-最初の場合はルート要素、2番目の場合はルート要素の子、したがって2番目の場合は一致します。一致する子孫だけが必要な場合は、代わりにDescendants()を使用します。

var query = from c in xmlFile.Descendants("Band") select c;

また、Xmlを再構築することをお勧めします:バンド名は、要素名ではなく属性または要素値である必要があります-これにより、クエリ(およびそのためのスキーマ検証)がはるかに難しくなります、つまり次のようになります:

<Band>
  <BandProperties Name ="Doors" ID="222" started="1968" />
  <Description>regular Band<![CDATA[lalala]]></Description>
  <Last>1</Last>
  <Salary>2</Salary>
</Band>
77
BrokenGlass

次の方法で実行できます。

xml.Descendants().SingleOrDefault(p => p.Name.LocalName == "Name of the node to find")

ここで、xmlはXDocumentです。

プロパティNameは、LocalNameとNamespaceを持つオブジェクトを返すことに注意してください。名前で比較する場合は、Name.LocalNameを使用する必要があります。

27

ルート要素を参照するには、 Root を使用する必要があります。

xmlFile.Root.Elements("Band")

ドキュメント内の任意の場所で要素を検索する場合は、代わりに Descendants を使用します。

xmlFile.Descendants("Band")
25
Mark Byers

問題は、Elementsdirectの呼び出し元の子要素のみを取ることです。すべての子孫が必要な場合は、 Descendants メソッドを使用します。

var query = from c in xmlFile.Descendants("Band")
6
Jon Skeet

大規模で複雑なXMLファイルを扱う際の私の経験では、特定の要素を取得する際に、ElementsもDescendantsも機能しないように見える場合があります(それでも理由はわかりません)。

そのような場合、次のMSDN投稿で説明されているように、要素を手動で検索する方がはるかに安全なオプションであることがわかりました。

https://social.msdn.Microsoft.com/Forums/vstudio/en-US/3d457c3b-292c-49e1-9fd4-9b6a950f9010/how-to-get-tag-name-of-xml-by- using-xdocument?forum = csharpgeneral

つまり、GetElement関数を作成できます。

private XElement GetElement(XDocument doc,string elementName)
{
    foreach (XNode node in doc.DescendantNodes())
    {
        if (node is XElement)
        {
            XElement element = (XElement)node;
            if (element.Name.LocalName.Equals(elementName))
                return element;
        }
    }
    return null;
}

次のように呼び出すことができます:

XElement element = GetElement(doc,"Band");

一致する要素が見つからない場合、これはnullを返すことに注意してください。

4
Human Wannabe

Elements()メソッドは、現在のノードのすべての子要素を含むIEnumerable<XElement>を返します。 XDocumentの場合、そのコレクションにはルート要素のみが含まれます。したがって、以下が必要です。

var query = from c in xmlFile.Root.Elements("Band")
            select c;
2
Phil Klein

Sebastianの答えは、xamlドキュメントを調べている間、私のために働いた唯一の答えでした。私のように、すべての要素のリストが必要な場合、メソッドは上記のセバスチャンの答えによく似ていますが、リストを返すだけです...

    private static List<XElement> GetElements(XDocument doc, string elementName)
    {
        List<XElement> elements = new List<XElement>();

        foreach (XNode node in doc.DescendantNodes())
        {
            if (node is XElement)
            {
                XElement element = (XElement)node;
                if (element.Name.LocalName.Equals(elementName))
                    elements.Add(element);
            }
        }
        return elements;
    }

次のように呼び出します:

var elements = GetElements(xamlFile, "Band");

または、すべてのTextBlockが必要なxamlドキュメントの場合は、次のように呼び出します。

var elements = GetElements(xamlFile, "TextBlock");
0
Ewan