Entwickler-Ecke

Dateizugriff - Alle knoten einer XML-Datei anzeigen lassen (mit XDOM)


ak - So 25.01.04 04:03
Titel: Alle knoten einer XML-Datei anzeigen lassen (mit XDOM)
Hallo Leute,

ich habe eine XML-Datei bei der ich theoretisch nicht weiss wie die einzelnen Knoten dieser Datei heissen. Jetzt frage ich mich wie ich durch die ganze Datei durchlaufen kann und mir dabei die Knotennamen und deren Inhalt anzeigen lassen kann. Das ganze will ich mit XDOM und Delphi 6 machen.

Folgenden code habe ich schon:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.Button1Click(Sender: TObject);
var
  Doc: TDOMDocument;
  List: TDomNodeList;
  Knoten: TDomNode;
  Len, i: Integer;
  S: string;
begin
  //Memo1.Clear;
  ListBox1.Items.Clear;

  Doc := XmlToDomParser1.FileToDom(extractfiledir(application.ExeName) + '\test.xml');

  List := Doc.documentElement.childNodes;

  Len := List.length;
  for i := 0 To List.length -1 do
    ListBox1.Items.Add(List.item(i).nodeName);

end;


Ich schaffe es einfach nicht alle Knoten und deren Inhalt in der Listbox anzuzeigen. Wie gesagt ich darf nicht wissen wie die Knote heissen. Habt ihr eine Idee?

Gruß AK


Delete - So 25.01.04 11:21
Titel: Re: Alle knoten einer XML-Datei anzeigen lassen (mit XDOM)
ak hat folgendes geschrieben:
Wie gesagt ich darf nicht wissen wie die Knote heissen. Habt ihr eine Idee?

Du meinst: du weißt nicht, wie die Knoten heißen, möchtest es aber herausfinden. ;)

Egal. Ich weiß nicht, ob eine Listbox das richtige ist. Ich habe dir mal ein Beispiel mit einem Tree-View gemacht. Aber weil ich nur D5 und die MS-XML-Typbibliothek habe, läuft mein Beispiel nicht mit der XML-Komponente, die du benutzt. So unähnlich sind sich die Befehle aber gar nicht. Ich bin der Meinung, du müsstest folgendes recht simpel "übersetzen" können.

Folgende Voraussetzung: du kennst die Knotennamen nicht, willst aber die komplette Datei (bzw. ihre Knoten) anzeigen lassen. In dem Fall brauchst du eine Prozedur oder Funktion, die sich selbst immer wieder aufruft - solange es eben untergeordnete Knoten gibt.
Nach dem Laden der XML-Datei habe ich den Tree-View "gesäubert" und dann die Prozedur aufgerufen. Geh bitte davon aus, dass "xmldoc" mein XML-Objekt ist (quasi das, was deiner Komponente entspricht):

Delphi-Quelltext
1:
GetThoseNodes(xmldoc.documentElement,nil);                    

Das nil bedeutet, es gibt zu diesem Zeitpunkt noch keinen übergeordneten Knoten im Tree-View. Logischerweise, denn hier wird ja mit "documentElement" der Root-Knoten des XML-Dokumentes übergeben.

Die Prozedur "GetThoseNodes" ist eine (meinem Button-Klick) untergeordnete Prozedur und sieht so aus:

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 GetThoseNodes(const xmlParent: IXMLDOMNode;
    tvParent: TTreeNode);
  var
    tn : TTreeNode;
    i  : integer;
    s  : string;
  begin
    // wenn der XML-Parent "nil" ist, dann raus!
    if(xmlParent = nilthen 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 = nilthen 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 > 0then
    // 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;

Wie gesagt, ich habe nicht diese Komponente (oder was immer das in deinem Fall ist), aber du müsstest Ähnlichkeiten feststellen können. So gesehen sollte es wirklich nicht schwer sein, die Prozedur für dein Programm umzubauen.

Gruß.

btw: user defined image [url=http://www.delphipraxis.com/topic17271_xmldatei+mit+xdom+komplett+auslesen.html]klick[/url]


ak - So 25.01.04 12:34

Danke für das Beispiel, ich schaue es mir mal an. Ich habe da so ein Buchvon Keith Wood, das nennt sich "Delphi und XML", für den praktischen Einsatz fast nicht geeignet. Da ist nicht ein einziges praktisches Beispiel drin, hauptsache aber alle Klassen aufgezählt. Muss mich immer noch aufregen über dieses Buch, ist zum Glück nur ausgeliehen.


ak - So 25.01.04 13:45

Danke Dir es klappt sehr gut.
Da es für XDOM (OPENXML) kaum praktische Anleitungen im Netz gibt, poste ich mal den angepassten Quelltext:


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:
35:
36:
37:
procedure TForm1.Button1Click(Sender: TObject);
var
  Doc: TDOMDocument;
begin

  tv.Items.Clear;

  Doc := XmlToDomParser1.FileToDom(extractfiledir(application.ExeName) + '\test.xml');
  GetThoseNodes(Doc.documentElement,nil);

end;

procedure TForm1.GetThoseNodes(const Knoten: TDomNode; tvParent: TTreeNode);
var
  tn : TTreeNode;
  len, i: Integer;
  s: string;
begin

  if (Knoten = nilthen exit;

  if (Knoten.nodeType = ntElement_Node) then
    s:=Knoten.nodeName
  else
    s:=Knoten.nodeValue;

  if (tvparent=nilthen
    tn:= tv.Items.Add(nil,s)
  else
    tn := tv.Items.AddChild(tvParent,s);

  if Knoten.childNodes.length >0 then
    for i := 0 to Knoten.childNodes.length - 1 do

  GetThoseNodes(Knoten.childNodes.item(i),tn);

end;


P.S. muss mich immer noch über das Buch aufregen, welches 683 Seiten hat und nicht ein praktisches Beispiel


Delete - So 25.01.04 14:17

Du kannst "GetThoseNodes" auch unterordnen (hm, wie heißt´n das richtig? :?). So hab´ ich´s gemacht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.Button1Click(Sender: TObject);

  procedure GetThoseNodes(const Knoten: TDomNode;
    tvParent: TTreeNode);
  { ... }

{ ... }

Auf die Weise hast du´s immer in der Prozedur. Es wäre ja möglich, dass du für ein anderes Programm etwas in der Art benötigst, dann musst du nicht erst lange suchen. ;)

Zitat:
P.S. muss mich immer noch über das Buch aufregen, welches 683 Seiten hat und nicht ein praktisches Beispiel

Everybody be cool! You: be cool! :mrgreen:
(Na, welcher Film?)


ak - So 25.01.04 14:25

Du weisst nicht zufällig wie ich im Knoten auf den Inhalt eines bestimmten Attributes zugreifen kann?


Delete - So 25.01.04 14:31

Ich verweise dich mal auf: XML: "gleiche" Objekte in einem Abschnitt? [http://www.delphi-forum.de/viewtopic.php?t=21148#124230] (Posting von gestern, 18 Uhr 41). Martin hatte so was. Der Quellcode ist aber wieder "nur" MS-XML. Aber du weißt ja nun wie´s geht ... ;)


ak - So 25.01.04 14:44

so gehts ;-) :


Delphi-Quelltext
1:
2:
3:
4:
if knoten.nodeName = 'knotenname1' then begin    
      showmessage(knoten.attributes.getNamedItem 
                           ('attribut1').textContent);
  end;


O'rallY - Sa 15.05.04 17:24

Bei einer XML Datei, die Zeilenumbrüche beinhaltet, werden in der Treeview Einträge mit einem oder zwei Balken angezeigt. (Ich benutze Open XML)
Woran kann das liegen?


Delete - So 16.05.04 08:40

Zwei Balken? So in der Art:

Quelltext
1:
Name des Eintrags||                    

Das ist der Zeilenumbruch. ;) Die Ursache dürfte wohl beim verwendeten XML-Parser zu suchen sein. Der Zeilenumbruch gilt intern als Textknoten. Manche Parser lassen sich davon nicht stören, bei anderen verfälschen sich die Ergebnisse. Open XML kenne ich nicht. Wenn du nicht versehentlich einen kleinen Fehler beim Auslesen gemacht hast, dann dürfte das Problem wohl am Parser liegen, der den Zeilenumbruch mit ausliest und zum Knoten zählt.