![]() |
Problem mit dem einlesen einer XML-Datei
Hallo,
ich habe das XML Tutorial von Choktay Gründlich gelesen und konnte alles an seinem Beispiel auch wunderbar nachvollziehen. Nun habe ich hier aber eine XML-Datei die etwas anderst aufgebaut ist, und egal wie ich es auch drehe und wende bekomme ich diese Datei nicht richtig ausgelsen! Ich habe zu meinem Problem auch schon hier in der DP gesucht, doch selbst eine Procedure von Matthias Simmack konnte mein Problem nicht lösen (GetThoseNodes)
Delphi-Quellcode:
Es werden zwar im TreeView neue knoten mit entsprechenden Bezeichnungen erstellt, jedoch sozusagen ohne Inhalt!//xmlDoc := CoDOMDocument40.Create usw. spare ich mir mal hier zu posten! //Ich lade die xml Datei 100% richtig, denn es wird ja auch was angezeigt //nur nicht korreckt! //Ich schreibe das nur um dies als Fehler schon einmal auszuschließen! procedure TForm1.GetThoseNodes(const xmlParent: IXMLDOMNode; tvParent: TTreeNode); var tn : TTreeNode; i : integer; s : string; begin // wenn der XML-Parent "nil" ist, dann raus! if(xmlParent = nil) then exit; // wenn der XML-Parent ein Element ist, dann // den Namen ermitteln, ... if(xmlParent.Get_nodeType = NODE_ELEMENT) then s := xmlParent.Get_nodeName // ... ansonsten den Inhalt else s := xmlParent.Get_nodeValue; // ist der TreeView-Parent "nil", dann neuen // Knoten an oberster Ebene einfügen, ... if(tvParent = nil) then tn := tv.Items.Add(nil,s) // ... ansonsten den Parent benutzen und den // neuen Knoten darunter einfügen else tn := tv.Items.AddChild(tvParent,s); // hat der XML-Parent noch untergeordnete Elemente? if(xmlParent.childNodes.length > 0) then // Ja, dann in einer Schleife diese Prozedur // hier erneut aufrufen, ... for i := 0 to xmlParent.childNodes.length - 1 do // ... und dabei das jeweilige Element sowie den // eben erzeugten TreeView-Knoten als Parents übergeben GetThoseNodes(xmlParent.childNodes.item[i],tn); end; Ich hoffe das mir das jemand erklären kann, anscheinend ist das ganze für einen Anfänger wohl noch etwas heavy... :gruebel:
XML-Code:
Gruß Bit
<?xml version="1.0" encoding="iso-8859-1" ?>
- <LISTE> - <Ordner name="Favoriten" hidden="0" locked="0"> <platz serviceID="0008" name="KLASSIK" onair="0085" /> <platz serviceID="000A" name="HIPHOP" onair="0085" /> <platz serviceID="000B" name="SOUL" onair="0085" /> <platz serviceID="002B" name="GROOVE" onair="0085" /> <platz serviceID="0009" name="MODERN" onair="0085" /> </Ordner> - <Ordner name="Musik" hidden="0" locked="0"> <platz serviceID="0004" name="MTV Classic" onair="013E" /> <platz serviceID="6FEE" name="MTV HITS" onair="0001" /> <platz serviceID="6FF8" name="MTV HITS." onair="0001" /> <platz serviceID="6FF9" name="MTV Base." onair="0001" /> <platz serviceID="0006" name="MTV 1" onair="013E" /> <platz serviceID="6FF3" name="MTV 2" onair="0001" /> </Ordner> </LISTE> |
Re: Problem mit dem einlesen einer XML-Datei
Ich habe die Prozedur, die im übrigen eh von mir ist ;), mal 1:1 aus dem Browserfenster übernommen und dazu noch deine XML-Datei. Was soll ich sagen? Keine Probleme. Allerdings habe ich sie erweitert, weil eine Anzeige wie
Code:
nicht wirklich aussagekräftig ist. Also, nimm meine Prozedur "GetThoseNodes" und füge zwischen
[-] LISTE
[-] Ordner platz platz platz
Delphi-Quellcode:
folgendes ein:
else
s := xmlParent.Get_nodeValue; // --> hier einfügen <-- // // ist der TreeView-Parent "nil", dann neuen // Knoten an oberster Ebene einfügen, ... if(tvParent = nil) then tn := tv.Items.Add(nil,s)
Delphi-Quellcode:
Voilà. Nun zeigt jeder gefundene Knoten in Klammern noch die Attribute an.
// Attribute anzeigen
if(xmlParent.attributes.length > 0) then begin s := s + ' ('; for i := 0 to xmlParent.attributes.length - 1 do s := s + xmlParent.attributes.item[i].Get_nodeName + '="' + xmlParent.attributes.item[i].Get_nodeValue + '" '; s := s + ')'; end; Aber hey: ein Problem hatte ich mit deiner XML-Datei, das will ich nicht verschweigen. Ich habe sie aus dem Browser in ein Notepad-Fenster kopiert und natürlich die drei Striche entfernt. Beim Speichern müssen noch irgendwelche Sonderzeichen drin gewesen sein, denn die Ausgabe sah sehr merkwürdig aus. Des Rätsels Lösung war, dass ich
Delphi-Quellcode:
benutzen musste, dann war das Problem vom Tisch.
xmldoc.preserveWhiteSpace := false;
Mehr Sorgen hatte ich nicht, und ich habe den Inhalt deiner Datei im Tree-View gesehen. Zitat:
|
Re: Problem mit dem einlesen einer XML-Datei
Zitat:
Code:
Das ist kein Fehler, höchstens der Beweis, dass entweder du das Prinzip von XML noch nicht richtig verstanden hast, bzw. dass Chakotays Tutorial noch nicht fertig ist. Oder beides :mrgreen:
[-] LISTE
[-] Ordner platz platz platz
Code:
"name", "hidden" und "locked" sind nämlich Attribute. Wie du schon an der gepatchten Funktion in meinem letzten Posting sehen kannst, musst du auf Attribute gesondert zugreifen, sonst siehst du natürlich nur die Knotennamen und ggf. den Inhalt.
<Ordner name="Favoriten" hidden="0" locked="0">
|
Re: Problem mit dem einlesen einer XML-Datei
Hi Matthias,
als erstes einmal: Zitat:
Wegen dem fehlenden Teil Sourcecode:
Delphi-Quellcode:
Auf jeden Fall vielen Dank für Deine schnelle Hilfe!
procedure TForm1.FormCreate(Sender: TObject);
var ... begin fAppPath:= ExtractFilePath(Application.ExeName); xmlDoc := CoDOMDocument40.Create; xmlDoc.setProperty('NewParser', true); ... xmlDoc.load(fAppPath + Servicliste); //Servicliste enthält den Pfad zur .xml ! ... end Ich werde es gleich mal ausprobieren, weiß allerdings nicht ob ich es heute noch schaffe mich hier im Forum dazu noch einmal zu äussern! Gruß Bit [Nachtrag: Unsere Postings haben sich gerade überschnitten! Das mit den Atributen wusste ich nicht, nun weiss ich bescheid! Das ist dann wohl eindeutig Chakotays schuld da er darüber in seinem Tutorial nichts erwähnt hat :mrgreen: |
Re: Problem mit dem einlesen einer XML-Datei
Nochmal ich ;)
Das klappt jetzt wunderbar, vielen Dank! Ein paar Fragen sind nun allerdings noch offen: 1- Wo finde ich den genauere Infos zum XML Format (Atribute usw. ...) 2- Ist es auch möglich aus den einzelnen Nodes nur bestimmte abschnitte heraus zu parsen ? Also statt: <platz serviceID="0009" name="MODERN" onair="0085" /> nur "MODERN" ; Gruß Bit P.S. Anmerkung zu 2: Ich will keine komplettlösung, dadurch wird man schnell lernfaul! Ich möchte nur wissen ob es da spezielle Funktionen / Prozeduren bei den XML Dateien gibt! Oder noch besser: Spezielle richtlinien an die ich mich halten muss vielleicht ? |
Re: Problem mit dem einlesen einer XML-Datei
Zitat:
Du musst nur unterscheiden lernen zwischen den herkömmlichen Knoten
Code:
zwischen Attributen
<Knoten>
<Unterknoten/> </Knoten>
Code:
und zwischen Versionsangaben, Parsinginfos usw. Wenn du MS-XML 4 installiert hast, dann wirf mal einen Blick in die mitgelieferte Hilfedatei. Oder, falls du das PSDK besitzt, dann schau dort rein, da findest du das gleiche Kapitel ebenfalls.
<Knoten Attribut="wert"/>
Zitat:
Delphi-Quellcode:
Wenn du also den Knoten mit einem bestimmten Attribut suchst, dann gibst du einfach das @ vor dem Attributnamen an. Und du siehst ja in meinem Codeauszug, dass du so ein Attribut auch als "normalen Node" ansprechen kannst:
node := xmldoc.selectSingleNode('//platz[@name="MODERN"]');
Delphi-Quellcode:
als Beispiel.
xmlParent.attributes.item[0].Get_nodeName
Zitat:
![]() |
Re: Problem mit dem einlesen einer XML-Datei
Hallo,
ich habe mir nun das MSXML 4.0 SDK installiert. Beim einfachen Setup von MSXML 4.0 wird das SDK nanscheinend nicht mitinstalliert, also vielen Dank für Deinen Hinweis :) Da habe ich ja jetzt eine gute Quelle zum Nachlesen ;) Gruß Bit |
Re: Problem mit dem einlesen einer XML-Datei
Code:
<?xml version="1.0" standalone="yes"?>
<datapacket day="26" month="8" year="2004" hour="15" min="06" sec="32" msec="386"> <metadata> <fielddefs> <fielddef name="Anrede" datatype="string" fieldsize="4" /> <fielddef name="Titel" datatype="string" fieldsize="5" /> <fielddef name="Vorname" datatype="string" fieldsize="255" /> <fielddef name="Nachname" datatype="string" fieldsize="255" /> <fielddef name="Positionswunsch" datatype="string" fieldsize="255" /> <fielddef name="Strasse" datatype="string" fieldsize="255" /> <fielddef name="PLZ" datatype="string" fieldsize="5" /> <fielddef name="Ort" datatype="string" fieldsize="255" /> <fielddef name="Land" datatype="string" fieldsize="255" /> </fielddefs> </metadata> <recorddata> <field name="Anrede" value="ghj"/> <field name="Titel" value="ghjgj."/> <field name="Vorname" value="gjghjg"/> <field name="Nachname" value="hjghj"/> <field name="Positionswunsch" value="ghjgj-ghj(m/w) - Norddeutghjgjschland"/> <field name="Strasse" value="ghj"/> <field name="PLZ" value="187876190" /> <field name="Ort" value="Gghjghjtz" /> <field name="Land" value="Deutschland" /> </recorddata> </datapacket> wie parse ich dieses recorddata? node.Get_nodeName --> gibt immer "field" aus node.xml --> gibt den xml code des aktuellen Knotens aus node.Get_text --> ist ja immer leer wie komme ich an die "name" und "value" felder? Über Get_NodeValue? ich habe gesehen dass im tutorial Get_NodeValue einen String zurückliefert. bei mir ist der rückgabewert aber vom typ oleVariant?! hab ich da was übersehen? hier mal mein code:
Code:
var
node: IXMLDOMNode; nodes: IXMLDOMNodeList; sOle: OleVariant; s: String; // Parsen des XML-Dokumentes begin xmlDoc := CoDOMDocument30.Create; //xmlDoc.setProperty('NewParser', true); --> nur für 4.0 Version! xmlDoc.validateOnParse := False; xmlDoc.resolveExternals := False; xmlDoc.async := False; xmlDoc.preserveWhiteSpace := False; if not xmlDoc.load(sDateiname) then MessageDlg('XML-Datei nicht vorhanden!', mtWarning, [mbOK], 0); // Durchlaufen einer NodeList: ----------------------------------------------- nodes := xmlDoc.selectNodes('//recorddata[0]/*'); node := xmlDoc.selectSingleNode('//recorddata[0]/*'); for i := 0 to nodes.length-1 do begin if (node <> nil) then begin node := nodes.nextNode; // einlesen des nodeValues, dabei ist das Ergebnis vom Typ OleVariant sOle := node.Get_nodeValue; case varType(sOle) of varStrArg: ShowMessage('COM-compatible string'); varEmpty : ShowMessage('The variant is Unassigned'); varOleStr : ShowMessage('Reference to a dynamically allo...'); varVariant : ShowMessage('A variant'); varString : ShowMessage('Reference to a dynamically ...'); varNull : ShowMessage('The variant is Null.'); varSmallint : ShowMessage('16-bit signed integer (type Sm....'); varInteger : ShowMessage('32-bit signed integer (type Integ...).'); varSingle : ShowMessage('Single-precision floating-point valu....'); varDouble : ShowMessage('Double-precision floating-point value (type double).'); varCurrency : ShowMessage('Currency floating-point value (type Currency).'); varDate : ShowMessage('Date and time value (type TDateTime).'); varDispatch : ShowMessage('Reference to an Automation object (an IDi....'); varError : ShowMessage('Operating system error code.'); varBoolean : ShowMessage('16-bit boolean (type WordBool).'); varUnknown : ShowMessage('Reference to an unknown object (an IInterface or IUnknown interface pointer).'); varByte : ShowMessage('A Byte'); varAny : ShowMessage('A CORBA Any value.'); end; { // wir wollen jetzt das Ergebnis vom Typ OleVariant // in einen String umwandeln iResult := VariantChangeType( sOle, sOle, 0, VT_BSTR); // das Ergebnis der Umwandlung prüfen case iResult of S_OK: ShowMessage('Success.'); DISP_E_BADVARTYPE: ShowMessage('The variant type vtNew ....'); DISP_E_OVERFLOW:ShowMessage('The data pointed to by p.....'); DISP_E_TYPEMISMATCH: ShowMessage('The argument could not ....'); E_INVALIDARG: ShowMessage('One of the arguments is invalid.'); E_OUTOFMEMORY: ShowMessage('Memory could not be allocated for the conversion.'); end; // wenn Ergebnis ok ist weiterverfahren ansonsten abbrechen if iResult <> S_OK then exit; } s := ''; //s := VarAsType(sOle, varString); // If VariantChangeType did not return an error, // the argument could then be fetched directly from the bstrVal field of the VARIANTARG //s:= sOle.bstrval; MessageDlg( 'lfd. Nr.: ' + #9 + IntToStr(i) + #13#10 + 'Nodename: ' + #9 + node.Get_nodeName + #13#10 + 'NodeInhalt: ' + #9 + node.xml + #13#10 + 'Get_NodeValue: ' + #9 + s + #13#10 + 'NodeGetText: ' + #9 + node.Get_text, mtInformation, [mbOK], 0); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz