Entwickler-Ecke

Dateizugriff - Anzahl der Element in einem XML File


alex_id - Di 13.01.04 19:15
Titel: Anzahl der Element in einem XML File
Hallo,

also ich würde gern wissen wie ich aus einer XML Dateii die Anzahll der Einträge / Elemente auslesen kann, d. h. wenn ich zB ein xml file mit folgender Struktur habe :

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
<?xml version="1.0"?>
<data>
         <element>
             <wert>1</wert>
         </element>
         <element>
            <wert>2</wert>
         </element> 
</data>


.... möchte ich herauslesen wieviele elemente in diesem File sind.
PS: die Struktur ist nur ein Beispiel !!!

Danke


Delete - Mi 14.01.04 09:50

Das kommt auf den XML-Parser an, den du verwenden möchtest. Ab Delphi 6 ist eine XML-Komponente dabei. Da ich aber nur D5 habe, kann ich dazu nichts sagen.
Vor Delphi 5 kannst du im Web XML-Komponenten finden, oder du importierst die MS-XML-Typbibliothek. Zu letzterer kann ich allerdings was sagen :), weil ich sie schon benutzt habe. Nachdem du die XML-Datei geladen hast (Beispiele gibt´s dazu einige hier im DF), kommst du mit

Quelltext
1:
xmldoc.documentElement                    

an den Hauptknoten (bei dir "data") und mir

Quelltext
1:
xmldoc.documentElement.childNodes.length                    

an die Anzahl der Unterknoten ran. In dem Fall werden aber alle Knoten gezählt, auch wenn´s vielleicht so aussieht:

Quelltext
1:
2:
3:
4:
5:
<data>
  <element/>
  <AndererName/>
  <element/>
</data>

Wenn du nur die "<element/>"-Knoten haben willst, kommst du mit XPATH und einer IXMLDOMNodeList-Variable am besten weg:

Delphi-Quelltext
1:
2:
3:
4:
5:
nl := xmldoc.selectNodes('/data/element');
if(nl.length > 0then
begin
  { ... }
end;

Auch dazu müsstest du einige Beispiele finden. Und in der [url=http://www.delphipraxis.net/forum43_xml.html]DP[/url] gibt´s ´ne eigene XML-Sparte. Vielleicht wirst du da noch schneller fündig (Sorry an die hiesigen Mods und Admins).


alex_id - Mi 14.01.04 10:57

Danke für die schnelle Hilfe ... werde es gleich mal testen ...
also ich hab folgendes probiert:

Delphi-Quelltext
1:
2:
 Form1.xmlDoc.documentElement.selectNodes('element');
 length := Form1.xmlDoc.childNodes.length;

nur leider bekomme ich immer nur 2 als Anzahl zurück obwohl 4 einträge vorhanden sind ...

Ich such noch mal im Forum... aber wenn du noch eine Idee hast :?: :roll:

Danke noch mal :!:

Alex


Delete - Mi 14.01.04 13:11
Titel: Re: Anzahl der Element in einem XML File
Ich hoffe, du bist nicht der Meinung, dass
alex_id hat folgendes geschrieben:

Quelltext
1:
2:
3:
<element>
  <!-- irgendwas dazwischen -->
</element>

zwei verschiedene Knoten sind? Wenn Ja, dann schäm dich! ;)


Quelltext
1:
<element>                    

ist der öffnende Knoten. Gemäß Konvention muss dieser Knoten aber auch wieder geschlossen werden. Das bedeutet, bei

Quelltext
1:
</element>                    

handelt es sich quasi immer noch um den gleichen Knoten. Und darum erhältst du IMHO auch den Wert 2, denn in deiner Beispieldatei gibt´s nur diese beiden "element"-Knoten. Das wird deutlicher, wenn die Knoten leer sind, dann kannst du die Datei nämlich auch so darstellen:

Quelltext
1:
2:
3:
4:
<data>
  <element/>
  <element/>
</data>

Falls es nicht um dieses Beispiel aus deinem ersten Posting geht, dann schau mal vorsichtshalber wg. der Schreibweise. Evtl. ist ein kleiner Tippfehler im Knotennamen, bspw.

Quelltext
1:
2:
3:
4:
5:
6:
<data>
  <element/>
  <elemant/>
  <element/>
  <elemend/>
</data>

;)

Gruß.


alex_id - Mi 14.01.04 16:52

nein ich habe das mit den Knoten schon verstanden (denke ich jedenfalls)
und meine Xml Datei sieht so aus :

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
<data>
  <element>
      <id>1</id>
  </element>
  <element>
      <id>2</id>
  </element>
  <element>
      <id>3</id>
  </element>
  <element>
      <id>4</id>
  </element>
</data>


und dennoch wird mir nur der Wert 2 zurückgegeben ...
was hab ich falsch gemacht ???

PS: ich bekomme auch den Wert 2 zurück wenn nur ein element enthalten ist ... ich finde das sehr werkwürdig :cry:


Delete - Mi 14.01.04 19:11

Was benutzt du eigentlich? Diese XML-Komponente von D6 und aufwärts, oder den MS-XML-Parser in Form der eingebundenen Typbibliothek? Ich werde bei Gelegenheit mal mit letzterem was versuchen und deine Beispieldatei benutzen, aber ich denke, ich bekomme das richtige Ergebnis.

Wenn sich also nicht irgendwo ein anderer Fehler eingeschlichen hat, dann sollte es aber in jedem Fall gehen - egal ob du nun die Komponente oder die Typbibliothek benutzt.


alex_id - Mi 14.01.04 20:13

Ich benutze D6 und MS XML V4.0 ...

Ich erkläre mal was ich vorhabe ...
ich möchte aus einer XML Datei mit beliebiger Länge die Elemente auslesen und dazu im Programm dann ein Objekt anlegen welches dann die Werte aus der Datei bekommt um mit diesen im Programm arbeiten zu können :!:

Jedoch habe ich in der ganzen Sache noch keinen richtigen Fortschritte gemacht :cry: :evil:

Hast du Anregungen oder ein Beispiel ???

Danke

Moderiert von user profile iconPeter Lustig: Doppelpost gelöscht


Delete - Mi 14.01.04 22:08

Also jetzt mal ausgehend von deiner XML-Datei (s. Posting von 15 Uhr 52) habe ich mit dem MS-XML-4-Parser folgenden Code probiert:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
procedure TForm1.Button1Click(Sender: TObject);
var
  xmldoc : DOMDocument40;
  nl     : IXMLDOMNodeList;
  i      : integer;
begin
  xmldoc := CoDOMDocument40.Create;

  if(xmldoc <> nilthen
  try
    xmldoc.async := false;
    xmldoc.resolveExternals := false;

    if(xmldoc.load(ExtractFilePath(paramstr(0)) + 'test.xml')) then
    begin
      nl := xmldoc.documentElement.selectNodes('element');

      if(nl.length > 0then
      begin
        ListBox1.Items.Add(
          Format('%d gefundene Knoten',[nl.length]));
        ListBox1.Items.Add('');

        nl := xmldoc.selectNodes('/data/element/id');
        if(nl.length > 0then
          for i := 0 to nl.length - 1 do
            ListBox1.Items.Add(Format('%d. "element/id" hat den Wert "%s"',
              [i+1,nl.item[i].text]));
      end;
    end;
  finally
    xmldoc := nil;
  end;
end;

In der Listbox wird zuerst die Anzahl der gefundenen "element"-Knoten angezeigt, danach die einzelnen "id"-Werte. Das ist eigentlich auch der Grundcode, den ich beim Laden von XML-Dateien benutze. So wie oben zu sehen funktioniert´s bei mir auch. Ich erhalte die 4 als Ergebnis.

Du kannst mit XPath auch Spielereien machen, bspw.:

Delphi-Quelltext
1:
2:
3:
nl := xmldoc.selectNodes('/data/element[id="2"]');
if(nl.length > 0then
  ShowMessage(nl.item[0].xml);

Musst du mal ausprobieren. ;) Oder schau mal ins Platform SDK von Microsoft. Wenn du XML 4 hast, dann müsstest du die entsprechende Hilfedatei aber auch haben. Kann ich nur empfehlen.

Gruß.


Miraculix - Mo 19.01.04 14:36

Hi an alle erst ma

In der Komponenten-palette gibt es die Komponente XML-Document.
da kannst du verschiedene Dinge auslesen

Mit XMLDocument1.DocumentElement liest du den OberKnoten aus in deinem Fall ist
DocumentElement: Data

um den Rest auszulesen könnest das so machen


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
  father, child: IXMLNode;
begin
  father := XMLDocument1.DocumentElement; 
  child := father.ChildNodes.First;                    //Erster Unterknoten 
  while child <> nil do                                  //solange es nen Knoten gibt
  begin

     child := child.NextSibling                    // Nächster Knoten der  Ebene   
  end;


um die ganze Hierarchie durch zugehen kannst du die While oder besser die Methode in die du die While Schleife schreibst rekursiv aufrufen

etwa so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure XMLLesen(father: IXMLNode);
var
  child : IXMLNode;
begin
  child := father.ChildNodes.First;                             //Erster Unterknoten 
  while child <> nil do                                  //solange es nen Knoten gibt
  begin
     {Knoten Attribute ...  auslesen}
     XMLLesen(child);                                         //Rekursion der Prozedur
     child := child.NextSibling                    // Nächster Knoten der  Ebene   
  end;                                                                 //Ende While Schleife
end;                                                                   //Ende Prozedur


einfach fragen bei Unklarheiten :D

Moderiert von user profile iconUGrohne: Delphi-Tags hinzugefügt


Delete - Mo 19.01.04 15:25

Warum so umständlich, Miraculix? Alex möchte bspw. wissen, wie viele Knoten namens "element" es in seiner XML-Datei gibt. Und das kannst du mit Hilfe des MS-XML-Parsers mit 2 Zeilen in Erfahrung bringen:

Delphi-Quelltext
1:
2:
nl := xmldoc.documentElement.selectNodes('element');
ShowMessage(Format('%d gefundene Knoten',[nl.length]));

Voilà.

Ich bin mir ziemlich sicher, dass diese XML-Komponente von Delphi 6 (und höher) das auch kann. Bei deiner while-Idee müsste man nämlich noch prüfen, ob der Knotenname auch wirklich "element" lautet.

Wenn es dagegen nur um die Anzahl aller Knoten geht (egal welchen Namen sie tragen), dann genügt bspw.

Delphi-Quelltext
1:
2:
ShowMessage(Format('%d gefundene Unterknoten',
  [xmldoc.documentElement.childNodes.length]));

Eine rekursive Funktion/Prozedur lässt sich ähnlich gestalten, so dass man relativ schnell die Anzahl aller Knoten, Unterknoten, Unterunterunter...knoten ermitteln kann, ohne deswegen die XML-Struktur einzeln durchlaufen zu müssen.

Das Einlesen bestimmter Knoten via XPath, etwa:
Zitat:

Delphi-Quelltext
1:
nl := xmldoc.selectNodes('/data/element[id="2"]');                    

ist ebenfalls eleganter und effizienter als alles der Reihe nach durchlaufen zu müssen. ;)


PeterPan - Do 14.07.05 14:28

hallo,

gibt es eine doku zu xml und d7?

thx
pp


Delete - Do 14.07.05 18:56

Eine Doku zu XML wirst du nicht finden, weil der Inhalt von XML ganz dir überlassen bleibt. Wenn du eine Doku zu einem XML-Parser meinst, dann kommt es darauf an, mit welchem du arbeiten willst. Für diese TXmlDocument-Komponente von Delphi kann ich dir keins nennen. Für MS-XML gibt es nur eine Anlaufstelle: das MS-XML SDK/PSDK/MSDN.