Einzelnen Beitrag anzeigen

aegidos

Registriert seit: 30. Okt 2007
40 Beiträge
 
Delphi 2007 Professional
 
#1

XML Find Node with Attribute

  Alt 19. Mär 2010, 14:40
Hallo,
Ich hab das Forum nun schon rauf und runter durchsucht, irgendwie trete ich bei folgendem Problem auf der Stelle:

Ich habe eine XML Datei:
<datagrid /> Dieser XML Datei möchte ich Knoten einhängen. Die Knoten heißen immer <data></data> und unterscheiden sich nur durch ein Attribut und den Wert.

Beispielsweise :
<data cname="b_Downloadfile">C:\Software\binary.bin</data>

Ich muss eine Hashtabelle durchlaufen welche zu jedem Namen auch einen Wert enthält. Ist eine Tabelle mit 2 Spalten in denen sich korrespondierende Paare befinden:
b_Downloadfile <--->C:\Software\binary.bin
c_Downloadfile <--->D:\Software\binary001.bin
Wenn meine XML Datei noch leer ist, dann ist es relativ einfach da ich über addchild einfach ein Daten-Node erzeuge und die Werte zuweise. Wo ich nicht ganz durchsteige wie ich abprüfe ob es den entsprechenden Node nicht schon in meiner XML gibt. weil dann will ich ihn nicht neu einfügen sondern den Wert überschreiben.

Mein Fortschritt bis dato:
Delphi-Quellcode:
procedure TLogDlg.SaveStringGrid( const FileName: TFileName);
var
  f: TextFile;
  i, k,l: Integer;
  tagFound: Integer;
  xmlTag : String;
  XMLDocumentDataGrid: TXMLDocument;
  newNode: IXMLNode;
begin
  l := 0;
  tagFound := 0;
  if FileExists(FileName)then
  begin

  XMLDocumentDataGrid := TXMLDocument.Create(Application);
  XMLDocumentDataGrid.FileName := FileName;
  XMLDocumentDataGrid.Active := true;

    // loop through cells -- Hashtabelle mit korrespondierenden Wertepaaren
    for i := 0 to LogDlg.dataGrid.RowCount - 1 do
      for k := 0 to LogDlg.dataGrid.ColCount - 1 do
      begin
        if (LogDlg.dataGrid.Cells[k, i] <> '')and (LogDlg.dataGrid.Cells[k+1, i] <> '') then
        begin
//in xmlTag steht der Wert den das Attribut cname dann bekommen soll
           xmlTag := StringReplace(LogDlg.dataGrid.Cells[k, i], ' ', '', [rfReplaceAll, rfIgnoreCase]);
            newNode:=XMLDocumentDataGrid.DocumentElement.ChildNodes.FindNode('data');
           while( newNode <> nil )do
           begin
           //data knoten schon vorhanden
                if(newNode.Attributes['cname'] = xmlTag)then
                begin
//hier habe ich bedenken denn eigentlich will ich ja den Wert in XMLDocumentDataGrid setzen und nicht in newNode .... liegt hier das Problem?
                          newNode.Text:=LogDlg.dataGrid.Cells[k+1, i];
                          tagFound := 1;
                          Break;
                end else begin
                        newNode := newNode.NextSibling;
                end;
           end;


        end;

      end;
       if (tagFound=0) then begin
             //no tag was found
             (XMLDocumentDataGrid.DocumentElement.AddChild('data').Attributes['cname']:=xmlTag);
//hier müsste ich nun noch dem eben hinzugefügten Knoten einen Wert hinzuweisen. Leider kann ich nicht alles in Klammern setzen und .Text beschreiben, wie geht denn das?
             XMLDocumentDataGrid.SaveToFile(FileName);
             XMLDocumentDataGrid.Active := False;
              SaveStringGrid(FileName);
           end else
           begin
                   XMLDocumentDataGrid.SaveToFile(FileName);
                   XMLDocumentDataGrid.Active := False;
           end;


  end;
end;
ABer irgendwie steht da immer nur das letzte korrespondierende Wertpaar drinnen wenn ich die XML Datei dann öffne.
was mir fehlt ist ein Befehl find Node with Name and Attribute Value
XMLDocumentDataGrid.DocumentElement.ChildNodes.FindNode('data').Attributes['cname'==xmlTag].Text :=LogDlg.dataGrid.Cells[k+1, i]; Hat hier jemand eine Idee?
Wenn ich XPath verwende dann kann ich das mit INodeXml nicht machen oder?
So ähnlich, nur ohne das .Value
//data[starts-with(@cname,xmlTag)].Value

Danke und schöne Grüße
Andi
  Mit Zitat antworten Zitat