none
LINQ XML Parent/Child nodes auslesen RRS feed

  • Frage

  • Hallo,

    Ich suche im moment eine lösung um aus einer XML datei die Parent/child Nodes so auszulesen das ich sie mit der verbindung zum Parent/child habe.

    So ansich auslesen kann ich die Parent/Child nodes.

    Meine XML sieht so aus:

     <Auftrag>
        <Nummer>7486234156</Nummer>
        <Bearbeiter>Maximilian</Bearbeiter>
        <auftragsnr>2012-852368</auftragsnr>
        <letztebearbeitung>09.05.2012 08:00:00</letztebearbeitung>
        <Projekt>
          <PName>Projekt Swordfischi</PName>
          <Nummer>75321458</Nummer>
          <adresse>
            <plz>11111</plz>
            <ortsname>Berlin</ortsname>
            <ortsteil>Kreuzberg</ortsteil>
            <strasse>Heinrichstr</strasse>
            <hausNr>49</hausNr>
          </adresse>
          <Auftraggeber>359DDS376A</Auftraggeber>
        </Projekt>
        <Projektbetreiber>
          <Name>Weihnachtsmann GmbH</Name>
          <adresse>
            <plz>11112</plz>
            <ortsname>Frankfurt</ortsname>
            <ortsteil>Mitte</ortsteil>
            <strasse>Hagbutta</strasse>
            <hausnr>23</hausnr>
          </adresse>
          <Partnernummer>554</Partnernummer>
        </Projektbetreiber>
        <termin>
          <terminVon>20.05.2012 08:00:00</terminVon>
    	  <alternativtermin></alternativtermin>
        </termin>
        <Auftragsbeschreibung>
          <uAuftragsbeschreibung>
            <Gruppe>Installation</Gruppe>
            <Nr>1</Nr>
            <auftragsbs>Installation H882/E 12</auftragsbs>
          </uAuftragsbeschreibung>
          <uAuftragsbeschreibung>
            <Gruppe>Installation</Gruppe>
            <Nr>2</Nr>
            <auftragsbs>Einrichtung H882/E 12</auftragsbs>
          </uAuftragsbeschreibung>
        </Auftragsbeschreibung>
      </Auftrag>


    Mein C# Code :

    // VARIANTE 1
                XDocument xmlDoc2 = XDocument.Load("c:\\a.xml");
                var nodeNames = xmlDoc2.Root.Descendants()
                                              .Select(eh => eh.Name.LocalName)
                                              .Distinct()
                                              .ToList();
    
               listBox1.Items.AddRange(nodeNames.ToArray());
    
    // VARIANTE 2
                XDocument xmlDoc2 = XDocument.Load("c:\\a.xml");
    
                IEnumerable<XNode> dnas =
                    from node in xmlDoc2.DescendantNodes()
                    select node;
                foreach (XNode node in dnas)
                {
                    if (node is XElement)
                        textBox1.Text = textBox1.Text + "\r\n"+ (node as XElement).Name;
                        //Console.WriteLine((node as XElement).Name);
                    else
                        textBox1.Text = textBox1.Text;
                        //Console.WriteLine(node);
                }


    Und so ist das ergebniss was ich erhalte bei beiden. Ohne die //---"" natürlich.

    Auftrag
    Nummer
    Bearbeiter
    auftragsnr
    letztebearbeitung
    Projekt  //--> CHILDNODE
    PName
    Nummer
    adresse //----GRANDCHILDNODE
    plz
    ortsname
    ortsteil
    strasse
    hausNr
    //-----------GRANDCHILDNODEENDE
    Auftraggeber
    
    //-----------CHILDNODEENDE
    Projektbetreiber //--> CHILDNODE
    Name
    adresse   //----GRANDCHILDNODE
    plz
    ortsname
    ortsteil
    strasse
    hausnr
    //-----------GRANDCHILDNODEENDE
    Partnernummer
    //-----------CHILDNODEENDE
    termin //--> CHILDNODE
    terminVon
    alternativtermin
    //-----------CHILDNODEENDE
    Auftragsbeschreibung //--> CHILDNODE
    uAuftragsbeschreibung  //----GRANDCHILDNODE
    Installation
    Nr
    auftragsbs
    //-----------CHILDNODEENDE
    Auftragsbeschreibung //--> CHILDNODE
    uAuftragsbeschreibung  //----GRANDCHILDNODE
    Installation
    Nr
    auftragsbs
    //-----------CHILDNODEENDE
    // ENDE XML

     Was ich aber gerne hätte wie es ausschauen soll ist:

    Auftrag
    Nummer
    Bearbeiter
    auftragsnr
    letztebearbeitung
    //Projekt  //--> CHILDNODE
    Projekt.PName
    Projekt.Nummer
    Projekt.adresse //----GRANDCHILDNODE
    Projekt.adresse.plz
    Projekt.adresse.ortsname
    Projekt.adresse.ortsteil
    Projekt.adresse.strasse
    Projekt.adresse.hausNr
    Projekt.Auftraggeber
    //Projektbetreiber //--> CHILDNODE
    Projektbetreiber.Name
    //Projektbetreiber.adresse   //----GRANDCHILDNODE
    Projektbetreiber.adresse.plz
    Projektbetreiber.adresse.ortsname
    Projektbetreiber.adresse.ortsteil
    Projektbetreiber.adresse.strasse
    Projektbetreiber.adresse.hausnr
    Projektbetreiber.Partnernummer
    //termin //--> CHILDNODE
    termin.terminVon
    termin.alternativtermin
    //Auftragsbeschreibung //--> CHILDNODE
    Auftragsbeschreibung.uAuftragsbeschreibung
    Auftragsbeschreibung.uAuftragsbeschreibung.Installation
    Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
    //Auftragsbeschreibung //--> CHILDNODE
    Auftragsbeschreibung.uAuftragsbeschreibung
    Auftragsbeschreibung.uAuftragsbeschreibung.Installation
    Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
    // ENDE XML

    Grund ist. Die Grandchild/Child elemente die selben namen sollen unterschiedlich bearbeitet werden. Ich bin gerade dabei IF verschachtelungen zu schreiben der überprüft ob die elemente vorhanden sind und dann bearbeitet. Aber dachte mir wäre doch schöner wenn ich das so direkt auslesen kann und dann weiterbearbeiten. Weil die XML datein haben zwar alle die selbe struktur, aber nicht immer gleich viele Childs/Grandchilds....

    Freitag, 18. Mai 2012 08:29

Antworten

  • So ganz konsistent erscheint mir dein gewünschtes Ergebnis nicht, so ist mir nicht klar, warum nicht "Auftrag" als Wurzelelement jeweils bei den Namen vorangestellt wird . Deshalb hier erst mal ein Beispiel, das folgendes ausgibt:

    Auftrag
    Auftrag.Nummer
    Auftrag.Bearbeiter
    Auftrag.auftragsnr
    Auftrag.letztebearbeitung
    Auftrag.Projekt
    Auftrag.Projekt.PName
    Auftrag.Projekt.Nummer
    Auftrag.Projekt.adresse
    Auftrag.Projekt.adresse.plz
    Auftrag.Projekt.adresse.ortsname
    Auftrag.Projekt.adresse.ortsteil
    Auftrag.Projekt.adresse.strasse
    Auftrag.Projekt.adresse.hausNr
    Auftrag.Projekt.Auftraggeber
    Auftrag.Projektbetreiber
    Auftrag.Projektbetreiber.Name
    Auftrag.Projektbetreiber.adresse
    Auftrag.Projektbetreiber.adresse.plz
    Auftrag.Projektbetreiber.adresse.ortsname
    Auftrag.Projektbetreiber.adresse.ortsteil
    Auftrag.Projektbetreiber.adresse.strasse
    Auftrag.Projektbetreiber.adresse.hausnr
    Auftrag.Projektbetreiber.Partnernummer
    Auftrag.termin
    Auftrag.termin.terminVon
    Auftrag.termin.alternativtermin
    Auftrag.Auftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Gruppe
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Gruppe
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
                XDocument doc = XDocument.Load("input.xml");
                List<string> names = doc.Descendants().Select(el => string.Join(".", el.AncestorsAndSelf().InDocumentOrder().Select(anc => anc.Name.LocalName).ToArray())).ToList();
                foreach (string name in names)
                {
                    Console.WriteLine(name);
                }

    So du das das vorangestellte "Auftrag" nicht willst, dann eventuell per

                List<string> names = doc.Descendants().Select(el => string.Join(".", el.AncestorsAndSelf().InDocumentOrder().Skip(1).Select(anc => anc.Name.LocalName).ToArray())).ToList();
    
    ansonsten musst du die Kriterien, nach denen die Namen zusammengefügt werden sollen, noch mal genauer erklären, so du mit den Vorschlägen das nicht selbst anpassen kannst.


    MVP Data Platform Development My blog

    • Als Antwort markiert mtotm Freitag, 18. Mai 2012 17:20
    Freitag, 18. Mai 2012 13:41

Alle Antworten

  • So ganz konsistent erscheint mir dein gewünschtes Ergebnis nicht, so ist mir nicht klar, warum nicht "Auftrag" als Wurzelelement jeweils bei den Namen vorangestellt wird . Deshalb hier erst mal ein Beispiel, das folgendes ausgibt:

    Auftrag
    Auftrag.Nummer
    Auftrag.Bearbeiter
    Auftrag.auftragsnr
    Auftrag.letztebearbeitung
    Auftrag.Projekt
    Auftrag.Projekt.PName
    Auftrag.Projekt.Nummer
    Auftrag.Projekt.adresse
    Auftrag.Projekt.adresse.plz
    Auftrag.Projekt.adresse.ortsname
    Auftrag.Projekt.adresse.ortsteil
    Auftrag.Projekt.adresse.strasse
    Auftrag.Projekt.adresse.hausNr
    Auftrag.Projekt.Auftraggeber
    Auftrag.Projektbetreiber
    Auftrag.Projektbetreiber.Name
    Auftrag.Projektbetreiber.adresse
    Auftrag.Projektbetreiber.adresse.plz
    Auftrag.Projektbetreiber.adresse.ortsname
    Auftrag.Projektbetreiber.adresse.ortsteil
    Auftrag.Projektbetreiber.adresse.strasse
    Auftrag.Projektbetreiber.adresse.hausnr
    Auftrag.Projektbetreiber.Partnernummer
    Auftrag.termin
    Auftrag.termin.terminVon
    Auftrag.termin.alternativtermin
    Auftrag.Auftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Gruppe
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Gruppe
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.Nr
    Auftrag.Auftragsbeschreibung.uAuftragsbeschreibung.auftragsbs
                XDocument doc = XDocument.Load("input.xml");
                List<string> names = doc.Descendants().Select(el => string.Join(".", el.AncestorsAndSelf().InDocumentOrder().Select(anc => anc.Name.LocalName).ToArray())).ToList();
                foreach (string name in names)
                {
                    Console.WriteLine(name);
                }

    So du das das vorangestellte "Auftrag" nicht willst, dann eventuell per

                List<string> names = doc.Descendants().Select(el => string.Join(".", el.AncestorsAndSelf().InDocumentOrder().Skip(1).Select(anc => anc.Name.LocalName).ToArray())).ToList();
    
    ansonsten musst du die Kriterien, nach denen die Namen zusammengefügt werden sollen, noch mal genauer erklären, so du mit den Vorschlägen das nicht selbst anpassen kannst.


    MVP Data Platform Development My blog

    • Als Antwort markiert mtotm Freitag, 18. Mai 2012 17:20
    Freitag, 18. Mai 2012 13:41
  • Danke, perfekte lösung.... Werde mir den Code mal genauer zu gute tun.
    Freitag, 18. Mai 2012 17:21