Announcement

Collapse
No announcement yet.

IXMLNode.Collection ist nil/Zugriffsverletzung

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • IXMLNode.Collection ist nil/Zugriffsverletzung

    Guten Tag, ich hatte heute meinen ersten Kontakt mit XML, zugrunde liegt eine einfache Datei wie:
    <PRE>
    <Jahr>
    <Firma>
    <Nummer>1</Nummer>
    <Name>Maier</Name>
    <Adresse>
    <Strasse>Holzweg</Strasse>
    <Ort>Bretten</Ort>
    <PLZ>75015</PLZ>
    </Adresse>
    </Firma>
    <Firma>
    <Nummer>2</Nummer>
    <Name>Schulz</Name>
    <Adresse>
    <Strasse>Rückweg</Strasse>
    <Ort>Karlsruhe</Ort>
    <PLZ>76133</PLZ>
    </Adresse>
    </Firma>
    <Kunde>Müller</Kunde>
    </Jahr>
    </PRE>
    Ich möchte nun die Anzahl der Knoten "Firma" erhalten und habe mit Hilfe der Online-Hilfe diesen Code geschrieben:
    <PRE>
    procedure TForm1.Button1Click(Sender: TObject);
    var
    LXMLDoc : TXMLDocument;
    LNode : IXMLNode;
    LNodeList : IXMLNodeList;
    LiCount : Integer;
    begin
    LNodeList := nil;
    try
    try
    LXMLDoc := TXMLDocument.Create(self);
    LXMLDoc.FileName := 'C:\Eigenes\test.xml';
    LXMLDoc.Active := True;
    LNodeList := LXMLDoc.documentElement.GetChildNodes;
    LNode := LNodeList.FindNode('Firma');
    LiCount := LNode.Collection.Count;

    </PRE>
    Hier gibt es nun eine Zugriffsverletzung und .Collection ist in dem Moment "nil". Aus der Online-Hilfe zu Collection werde ich nicht ganz schlau, muss ich zwischen den letzten beiden Code-Zeilen noch was einfügen, oder wie wird Collection gefüllt ?

    Desweiteren ist mir nicht klar, wie ich mich innerhalb einer bestimmten "Knoten-Ebene" nur durch die speziellen Knoten (hier: Firma) bewege, dazu müsste ich doch eine Auswahlmenge haben, in der sich diese speziellen Knoten mit ihren Unterknoten befinden (ähnlich einer Query bei Datenbankzugriffen) und die ich mittels Schleife durchlaufen kann, wäre das dann die Collection, aber wie bewege ich mich in der ?

    Vielen Dank im Voraus für Ihre Hilfe

    Michael

  • #2
    Hallo.

    Ich habe bisher noch nie mit diesem TXMLDocument gearbeitet, und vielleicht irre ich mich: aber das scheint mir doch sehr umständlich zu sein. Auf die Schnelle habe ich nichts zum Suchen von bestimmten Knoten (die ja auch mehrfach auftreten können) gefunden. Aber ich glaube, dass "Collection" nicht das Richtige ist.
    Wie gesagt: ich habe keine Erfahrungen mit dieser Komponente, weil ich immer direkt die MS-XML-Typbibliothek verwende, mit der deine Aufgabe relativ simpel gelöst werden könnte:

    <pre><b>var</b>
    xmldoc : DomDocument40; <i>// MS-XML 4</i>
    nl : IXMLDOMNodeList;
    i : integer;
    <b>begin</b>
    xmldoc := CoDomDocument40.Create;
    <b>if</b>(xmldoc &lt;&gt; <b>nil</b>) <b>then</b>
    <b>try</b>
    xmldoc.async := true;
    xmldoc.resolveExternals := false;
    xmldoc.preserveWhiteSpace := true;<br>
    <b>if</b>(xmldoc.load(ExtractFilePath(paramstr(0)) + 'test.xml')) <b>then</b>
    <b>begin</b>
    nl := xmldoc.selectNodes('//Jahr/Firma');
    <b>if</b>(nl.length &gt; 0) <b>then</b>
    <b>for</b> i := 0 <b>to</b> nl.length - 1 <b>do</b>
    ShowMessage(nl.item[i].xml);<br>
    <b>end</b>;
    <b>finally</b>
    xmldoc := <b>nil</b>;
    <b>end</b>;
    <b>end</b>;</pre>

    XML 4 kann bei Microsoft heruntergeladen und installiert werden, sofern noch nicht vorhanden. Danach kannst du in Delphi über das Menü "Projekt -> Typbibliothek importieren" die notwendige Unit anlegen lassen und dann nutzen. Durch <i>XPath</i> ergeben sich noch mehr Spielereien. Ich will nicht sagen: Wie bei einer Datenbank, denn der Vergleich würde ein bisschen hinken ... aber fast. :-D
    Wenn du bspw. wissen willst, wer auf dem Holzweg ist ... äh, im Holzweg wohnt, dann genügt:

    <pre>node := xmldoc.selectSingleNode('//Jahr/Firma' +
    '[Adresse/Strasse=&quot;Holzweg&quot;]' +
    '/Name');
    <b>if</b>(node &lt;&gt; <b>nil</b>) <b>then</b>
    ShowMessage(node.text);</pre>

    (Ich habe die Auswahl nur untereinander geschrieben, weil die Zeile sonst evtl. zu lang geworden wäre.) Diese Anweisung benutzt den untergeordneten Knoten "Adresse/Strasse" zum Vergleich und liefert dir dann den Inhalt von "Name" zurück:

    <pre>&lt;Firma&gt;
    &lt;Nummer&gt;1&lt;/Nummer&gt;
    <b>&lt;Name&gt;Maier&lt;/Name&gt;</b>
    <b style="color:#ff0000;">&lt;Adresse&gt;
    &lt;Strasse&gt;Holzweg&lt;/Strasse&gt;</b>
    &lt;Ort&gt;Bretten&lt;/Ort&gt;
    &lt;PLZ&gt;75015&lt;/PLZ&gt;
    &lt;/Adresse&gt;
    &lt;/Firma&gt;</pre>

    Einen Nachteil gibt es: Im Gegensatz zur Komponente wird hier nichts integriert, so dass dein Programm, bzw. der XML-Teil, nur lauffähig ist, wenn auf dem Zielrechner auch die benutzte XML-Version vorhanden ist. Du musst also selbst prüfen ob das der Fall ist und das Programm ggf. mit einem Hinweis beenden; idealerweise noch <b>vor</b> dem Erzeugen irgendwelcher Forms, usw. Eine Hilfsroutine hätte ich anzubieten:
    http://www.delphipraxis.net/topic15622_pruefen+ob+msxml+installiert+ist.html

    Aber hey, ich will dich jetzt nicht von TXMLDocument abbringen. ;-)
    Frage an die richtigen Profis: So was wie <i>XPath</i> müsste diese Komponente doch auch haben. Oder? Soweit ich weiß, lässt sich doch MS-XML sogar als DOMVendor festlegen.

    Gruß

    Comment


    • #3
      Hallo Mathias,

      vielen Dank für Ihre ausführliche Antwort, ich werds mir mal genau zu Gemüte führen. Da Sie am Ende den DOMVendor erwähnen, dürfte ich Sie hierzu auch noch mal "missbrauchen", ich habe unter Delphi und XML noch eine Frage genau dazu gepostet ("Was ist DOMVendor?"), auf die ich bislang noch keine Antwort erhielt, gerade deshalb weil Sie sich in Punkto XML wohl auch hoch nicht als "Hardcore-Profi" sehen, könnte ich mir denken, dass Sie mir das verständlich erklären könnten. Wenn Si mal die Zeit dazu fänden, wäre das sehr nett, soweit erstmal vielen Dank, freundliche Grüsse
      Michae

      Comment


      • #4
        Nur unter der Bedingung, dass du mit dem "Sie" aufhörst. ;o)<br><br>
        Also, wenn ich das richtig sehe, dann enthält mein Delphi 7 drei verschiedene (ich nenn´s mal "Anbieter": MSXML (Microsoft), XerxesXML (?) und OpenXML (http://www.philo.de/xml/).
        Aus diesen kannst du wählen, was bestimmt irgendwie Auswirkungen auf die Art und Weise hat, mit der das XML-Dokument geparst wird und bearbeitet werden kann. Das bringt mich auf die Idee, dass es vielleicht doch eine Möglichkeit geben muss, auf die Vorteile einzelner Anbieter zuzugreifen. Ich meine, wenn MSXML schon unterstützt wird, dann könnte man evtl. auch die ganzen Sachen nutzen, die ich in meinem ersten Posting beschrieben habe.<br><br>
        Aber wie gesagt: ich hab´s bisher nie gebraucht, darum ist das alles nur die blanke Theorie. Evtl. findet sich hier jemand, der es genauer weiß und besser erklären kann.<br><br>
        Gruß

        Comment


        • #5
          Hallo Mathias,

          ok, "ich bin der Michael" ;-).<BR>
          Das mit den drei Anbietern hab ich auch gesehen, als ich die Komponente testweise verwendet habe, man kann dann einen von denen auswählen. In meinem tatächlichen Projekt erzeuge ich aber das Objekt selbst und da liegt jetzt das Problem, mit auswählen geht jetzt halt nix mehr, ich muss DOMVendor direkt was zuweisen und da weiss ich eben nicht was, also was entspricht dem was ich im Objektinspektor der Property DOMVendor zuweise wenn ich z.B. MSXML auswähle ? Und dann eben das Problem, muss was mit ausgeliefert werden und falls ja was und wie, ich weiss nicht ob ich mich einfach so drauf verlassen kann, dass es beim Anwender immer funktioniert.

          Gruss
          Michae

          Comment

          Working...
          X