it-swarm.com.de

Element in XDocument finden?

Ich habe ein einfaches 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>

Jedoch , 

wenn ich die "Doors-Band" erreichen und ihre ID ändern möchte: 

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

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

                            select c;
                             ...

query hat keine Ergebnisse

Aber

Wenn ich xmlFile.Elements().Elements("Band") schreibe, findet es es.

Worin besteht das Problem ?

Ist der vollständige Pfad vom Root aus erforderlich?

Und wenn ja, warum hat es funktioniert, ohne AllBands anzugeben?

Erfordert die XDocument-Navigation, dass ich die vollständige Struktur der Ebene bis zum erforderlichen Element kenne?

49
Royi Namir

Elements() prüft nur direkte untergeordnete Elemente. Dies ist im ersten Fall das Wurzelelement, im zweiten Fall die untergeordneten Elemente des Wurzelelements. Daher wird im zweiten Fall eine Übereinstimmung angezeigt. Wenn Sie nur einen passenden Nachkommen haben möchten, verwenden Sie stattdessen Descendants():

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

Außerdem würde ich vorschlagen, dass Sie Ihr XML neu strukturieren: Der Bandname sollte ein Attribut oder ein Elementwert sein, nicht der Elementname selbst. Dies macht das Abfragen (und die Schemavalidierung für diese Angelegenheit) viel schwieriger, d. H.

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

Sie können es so machen:

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

dabei ist XML ein XDocument.

Beachten Sie, dass die Eigenschaft Name ein Objekt zurückgibt, das über einen LocalName und einen Namespace verfügt. Deshalb müssen Sie Name.LocalName verwenden, wenn Sie nach Namen vergleichen möchten.

27

Sie sollten Root verwenden, um auf das Stammelement zu verweisen:

xmlFile.Root.Elements("Band")

Wenn Sie Elemente im Dokument finden möchten, verwenden Sie stattdessen Descendants :

xmlFile.Descendants("Band")
23
Mark Byers

Das Problem ist, dass Elements nur die untergeordneten direct -Elemente von dem übernimmt, für den Sie es aufrufen. Wenn Sie alle Nachkommen wünschen, verwenden Sie die Methode Descendants :

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

Bei der Arbeit mit großen und komplizierten XML-Dateien habe ich die Erfahrung gemacht, dass manchmal weder Elemente noch Nachkommen beim Abrufen eines bestimmten Elements zu arbeiten scheinen (und ich weiß immer noch nicht, warum). 

In solchen Fällen habe ich festgestellt, dass es eine viel sicherere Option ist, manuell nach dem Element zu suchen, wie in dem folgenden MSDN-Beitrag beschrieben:

https://social.msdn.Microsoft.com/Forums/vstudio/de/3d457c3b-292c-49e1-9fd4-9b6a950f9010/wie-zu-ziel-tag-name-von-xml-von-nutzungs- xdocument? forum = csharpgeneral

Kurz gesagt, Sie können eine GetElement-Funktion erstellen:

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

Das kannst du dann so anrufen:

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

Beachten Sie, dass dies null zurückgibt, wenn kein übereinstimmendes Element gefunden wird.

4
Human Wannabe

Die Elements()-Methode gibt einen IEnumerable<XElement> zurück, der alle untergeordneten Elemente des aktuellen Knotens enthält. Bei einem XDocument enthält diese Auflistung nur das Root-Element. Daher ist Folgendes erforderlich:

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

Sebastians Antwort war die einzige, die bei der Prüfung eines XAML-Dokuments für mich funktionierte. Wenn Sie, wie ich, eine Liste aller Elemente haben möchten, würde die Methode der von Sebastians Antwort oben sehr ähneln, aber nur eine Liste zurückgeben ...

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

Nenne es so:

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

oder bei meinem xaml doc, wo ich alle TextBlocks haben wollte, nenne es so:

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