XML parsen
bernd2k
- asp.net
1 Frank (no reg)0 Bernd2k0 Frank (no reg)
Hallo,
also ich komme nicht weiter. Kann man mit VB/ ASP denn überhaupt effizient XML Dokumente parsen? Sicher, nur versteh ich es wahrscheinlich nicht.
Ich habe eine XML-Datei die wie folgt aufgebaut ist
<buecher>
<buch>
<autor>AAA</autor>
<titel>BBB</titel>
</buch>
<buch>
.....
</buecher>
Ich komme einfach nicht dahinter wie ich auf die Elemte zugreifen kann. In PHP ist das so easy.
Habe es bis jetzt soweit, aber da kommt zwar alles raus, was ich brauche, aber alles vollkommen unstrukturiert. Ich weiss also nicht, wann ein <buch> abgearbeitet ist und wann das naechste anfaengt.
Set rootNode = XMLDoc.documentElement
If rootNode.hasChildNodes() Then
For Each buch in rootNode.childNodes
response.write rootNode.nodeName & ": " & buch.Text & "<p>"
next
end if
Ausserdem kann ich mit rootNode.nodeName nicht auf den Namen des Tags wie "autor" und "titel" zugreifen.
Wo liegt mein Verstaendnisproblem? Ich dachte die Parser sind soweit, dass mir eine Information geliefert wird, wann ein Element <buch> abgearbeitet ist.
Danke
Hallo,
um XML Dokumente zu parsen benutzt man für gewöhnlich eine entsprechende Komponente, für MS/ASP/VB wäre es beispielsweise der MSXML Parser in der jeweilig zur Verfügung stehenden Version. Der hat dann Klassen, die DOM implementieren und in deren Instanzen man XML Markup laden kann.
Ich habe eine XML-Datei die wie folgt aufgebaut ist
<buecher>
<buch>
<autor>AAA</autor>
<titel>BBB</titel>
</buch>
<buch>
.....
</buecher>
Ich komme einfach nicht dahinter wie ich auf die Elemte zugreifen kann. In PHP ist das so easy.
Dafür gibt es die .ChildNodes Collection von XmlNode sowie die Methoden Select/SelectSingleNode von XmlNode
Habe es bis jetzt soweit, aber da kommt zwar alles raus, was ich brauche, aber alles vollkommen unstrukturiert. Ich weiss also nicht, wann ein <buch> abgearbeitet ist und wann das naechste anfaengt.
Was ist unstrukturiert? Das du eine Schleife benutzt um jedes XmlNode Object in der XmlNode.ChildNodes Collection verarbeiten zu können. <buch> ist in dem Fall ein XmlNode aus XmlDoc.DocumentElement.ChildNodes. Das DocumentElement hat den Namen "buecher". Mit jeder Schleifeniteration arbeitest du also genau ein <buch> ab. Was ist daran so schwer?
Set rootNode = XMLDoc.documentElement
If rootNode.hasChildNodes() Then
For Each buch in rootNode.childNodes
response.write rootNode.nodeName & ": " & buch.Text & "<p>"
next
end ifAusserdem kann ich mit rootNode.nodeName nicht auf den Namen des Tags wie "autor" und "titel" zugreifen.
rootNode.NodeName zeigt auch auf das DocumentElement, <buecher>. Und nicht auf eines der Objekte "buch" aus der DocumentElement.ChildNodes Collection. "buch" selbst beinhaltet übrigens gar keinen eigenen .Text
Wo liegt mein Verstaendnisproblem? Ich dachte die Parser sind soweit, dass mir eine Information geliefert wird, wann ein Element <buch> abgearbeitet ist.
Die Parser selbst wohl schon, nur muss ihnen auch gesagt werden, was sie tun sollen. Wenn du den InnerText Wert <autor> haben willst, dann solltest du auch auf diesen Node zugreifen. z.b. mit
Set rootNode = XMLDoc.documentElement
If rootNode.hasChildNodes() Then
For Each buch in rootNode.childNodes
autorNode = buch.SelectSingleNode("autor")
response.write autorNode.nodeName & ": " & autorNode.Text & "<p>"
Next
End If
Hilft dir das jetzt etwas weiter?
Cheers,
Frank
Hallo,
erst mal vielen Dank fuer die ausfuehrliche Antwort!
um XML Dokumente zu parsen benutzt man für gewöhnlich eine entsprechende Komponente, für MS/ASP/VB wäre es beispielsweise der MSXML Parser in der jeweilig zur Verfügung stehenden Version. Der hat
Okay, das hab ich und ich benutze den MSXML-Parser auch.
Ich habe eine XML-Datei die wie folgt aufgebaut ist
<buecher>
<buch>
<autor>AAA</autor>
<titel>BBB</titel>
</buch>
<buch>
.....
</buecher>Ich komme einfach nicht dahinter wie ich auf die Elemte zugreifen kann. In PHP ist das so easy.
Dafür gibt es die .ChildNodes Collection von XmlNode sowie die
Okay, das verstehe ich auch. Mein Problem liegt vielleicht dabei, dass ueber <buecher> noch ein Element <bibliothek> liegt. Kann man denn den Einstiegspunkt des rootNode angeben? Denn mit
Set rootNode = XMLDoc.documentElement
greift der auf <bibliothek> zu und nicht auf <buecher>
Ich habe mir dann etwas rekursives zusammengebaut.
Das greift dann auf die tieferliegenden Elemnte genau so zu, wie ich es will, ABER, ich bekomme vom Parser keine Rueckmeldung/ ein Flag oder aehnliches, wann denn ein 'childNode' angearbeitet ist.
Ich moechte bspw. jedes <buch> auf einer HTML-Seite ausgeben und nach jedem Buch ein Trennstrich ziehen.
Bis jetzt faellt mir nur eine Konstruktion ein mitzuzaehlen, wie oft der Parser <buch> gefunden hat und wenn die Anzahl grade ist, muss er wohl </buch> gefunden haben und ich weiss, dass ich jetzt den Trennstrich ziehen kann. Das kann doch aber nicht wirklich so gedacht sein, oder? Liefert denn der Parser nichts zurueck, dass er einen Knoten abgearbeitet hat?
Methoden Select/SelectSingleNode von XmlNode
Hm, das muss ich mir mal anschauen
Was ist unstrukturiert? Das du eine Schleife benutzt um jedes XmlNode Object in der XmlNode.ChildNodes Collection verarbeiten zu können. <buch> ist in dem Fall ein XmlNode aus XmlDoc.DocumentElement.ChildNodes. Das DocumentElement hat den Namen "buecher". Mit jeder Schleifeniteration arbeitest du also genau ein <buch> ab. Was ist daran so schwer?
Eben dass ich nicht mitbekomme, wann ein <buch> 'abgearbeitet' ist.
was sie tun sollen. Wenn du den InnerText Wert <autor> haben willst, dann solltest du auch auf diesen Node zugreifen. z.b. mit
Set rootNode = XMLDoc.documentElement
If rootNode.hasChildNodes() Then
For Each buch in rootNode.childNodes
autorNode = buch.SelectSingleNode("autor")
response.write autorNode.nodeName & ": " & autorNode.Text & "<p>"
Next
End If
Ja, das geht, wenn das nur einmal verschachtelt ist, aber ich bekomme nicht mit, wann ein <buch> fertig ist, wenn ein childNode noch mal childnodes hat. Also wie bei mir, wo ueber <buecher> noch <bibliothek> liegt.
Mein Versuch bis jetzt
Ich habe auch mal versucht, ob mir der Parser nur die Elemente rausholt die <buch> sind. Aber mit
liste = XMLDoc.GetElementsByTagName("buch")
bekomme ich nur den Fehler "Wrong number of arguments or invalid property assignment: 'liste'" geliefert.
Danke noch mal fuer deine Hilfe, evtl. habe ich ein tieferliegendes Verstaendnisproblem, da ich mir nicht vorstellen kann, dass das so schwierig sein kann, da XML ja nun wirklich ueberall genutzt wird.
Hallo,
ein MSXML.XMLNode hat eine Collection von untergeordneten XMLNode Objekten, .ChildNodes genannt. Durch diese kann man mittels einer "for each" Schleife iterieren. Ein Element der Collection ist dann quasi abgearbeitet, wenn die Schleife zum nächsten Durchgang gelangt, also wenn man (der Entwickler) das "Next" Kommando der Schleife ausführt. Bis dahin bleibt man im Kontext des aktuellen Elements aus der Iteration. In deinem Falle Buch.
Wenn ich dich richtig verstehe, dann solltest du vor dem NEXT einfach noch ein Response.Write "Trennstrich" & "<br/> platzieren.
Du hast aber anscheinend generell ein Verständnisproblem mit der Benutzung des DOM Modells vom XMLDomDocument.
Die Funktion XMLDoc.GetElementsByTagName("buch") wird evt. nicht nur ein Argument benötigen? Vielleicht gibt es sie auch gar nicht. Schau dir in deinem Entwicklungsstudio bzw. im MSDN die Objektreferenz vom MSXML Parser an.
Eine imho recht effektive Sache zur Ermittlung aller <buch> elemente ist:
XMLDoc.DocumentElement.SelectNodes("//buch") das gibt dir eine XmlNodeList (iirc) zurück, die du mit einer "for each" schleife iterieren kannst. XmlNodeList beinhaltet dann XmlNodes mit dem NodeName "buch" und (wahrscheinlich) den Childnodes <autor> und <titel>. "//buch" ist dabei ein XPATH Query
Wenn du meinst, mit PHP ist das so einfach, wie stellst du denn da fest, wann ein <buch> _abgearbeitet_ ist?
Cheers, so long,
Frank
ein MSXML.XMLNode hat eine Collection von untergeordneten XMLNode Objekten, .ChildNodes genannt. Durch diese kann man mittels einer "for each" Schleife iterieren. Ein Element der Collection ist dann quasi abgearbeitet, wenn die Schleife zum nächsten Durchgang gelangt, also wenn man (der Entwickler) das "Next" Kommando der Schleife ausführt. Bis dahin bleibt man im Kontext des aktuellen Elements aus der Iteration. In deinem Falle Buch.
Hm, das ist klar. Nur durch die 2fache Verschachtelung (<bibliothek> -> <buecher> -> <buch>) erhalte ich immer nur das Ende der ersten Ebene.
Also ich weiss immer wann <buecher> abgearbeitet ist, aber nicht wann <buch> fertig ist. Ich kann mir zwar alles unterhalb von <buch> ausgeben lassen, weiss aber nie, wann ich den Trennstrich ziehen kann.
Wenn du meinst, mit PHP ist das so einfach, wie stellst du denn da fest, wann ein <buch> _abgearbeitet_ ist?
Bei PHP kann ich mir alle Elemente eines bestimmten Nodes in einer Liste geben lassen mit z.B.
$domNode=$rootDomNode->get_elements_by_tagname("buecher");
Dadurch habe ich einen Einsprungpunkt, wo keine weitere Verschachtelung mehr auftritt.
Dann kann ich mit einer Schleife durch die Liste durchgehen und dann jedes Buch EINZELN bearbeiten.
Aber vielen Dank fuer deine Hilfe. Werd mir das auch noch mal anschauen und deine Tipps abarbeiten.
Aber ich denke auch eher, dass es daran liegt, dass mir verstaendnissmaessig das Konzept XML an sich nicht in den Kopf will.
Ich persoenlich finde es schon komisch, mich erst in eine Struktur einarbeiten zu muessen, um dann erst die Daten herausholen zu koennen. Aber das tut hier ja eigentlich nichts zur Sache :-)
Hallo,
wenn du mit VB arbeitest, must du für zuweisung von Objekt Instanzen zu Variablen das Keyword SET davorschreiben:
nicht: liste = XMLnode.Select ...
Sondern SET liste = XMlNode.Select ...
Nur durch die 2fache Verschachtelung (<bibliothek> -> <buecher> -> <buch>) erhalte ich immer nur das Ende der ersten Ebene.
Dann schreibst du halt 2 Schleifen ineinander (ist zwar nicht wirklich die allgemeingültige Lösung) aber
mit
$domNode=$rootDomNode->get_elements_by_tagname("buecher");
und darauffolgender Abarbeitung von $domNode in einer Schleife machst du auch nix anderes als wenn du es in VB machen würdest. Nur dass beim MSXML Parser vielleicht manche Funktionen anders heissen oder nicht vorhanden sind gegenüber PHP und das Schleifen vielleicht anders deklariert werden als du gewohnt bist. Da ne Schleife und dort ne Schleife, genau dasselbe, und darin bearbeitest du dann das Element was gerade für den Schleifendurchlauf X aktuell ist.
Ich persoenlich finde es schon komisch,
Wenn du es komisch findest, warum benutzt du dann XML. Zum Experimentieren, okay, aber wenns für eine konkrete Aufgabenstellung ist, schau doch mal ob nicht andere Techniken dasselbe Ergebnis liefern und dabei einfacher für dich sind. Man muss XML nicht verwenden nur weil es es gibt.
Seitdem es MS SQL 2005 gibt, welcher nativ XML unterstützt samt XQuery usw spriessen die Lösungen dafür (wo auch dieses XML-Feature benutzt wird) quasi wie Pilze aus dem Boden, aber unter ca. 30 Systemen, die ich bislang zur Revision anschauen durfte, waren vielleicht 3 oder 4 dabei, wo die Benutzung von XML a) Sinn machte (weil sonst nix anderes möglich) and/or/xor b) sinnvoll implementiert wurde. Typische Entwicklerkrankheit, immer das neueste und fancy-este zu nehmen :)
Cheers,
Frank
Hallo,
Die Funktion XMLDoc.GetElementsByTagName("buch") wird evt. nicht nur ein Argument benötigen? Vielleicht gibt es sie auch gar nicht. Schau dir in deinem Entwicklungsstudio bzw. im MSDN die Objektreferenz vom MSXML Parser an.
Also laut http://www.topxml.com/xml_dom/getelementsbytagname.asp#P4300_94286 sollte das so gehen.
Eine imho recht effektive Sache zur Ermittlung aller <buch> elemente ist:
XMLDoc.DocumentElement.SelectNodes("//buch") das gibt dir eine XmlNodeList (iirc) zurück, die du mit einer "for each" schleife iterieren kannst.
Hab ich probiert, auch da erhalte ich als Fehler:
"Wrong number of arguments or invalid property assignment:"
Leider finde ich nichts, woran das liegen koennte, denn auch hier finde ich bei http://www.topxml.com/xml_dom/selectnodes.asp#P4741_114632 nichts, was auf weitere Argumente als zu uebergebende Parameter hinweist.
Danke