AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein XML Delphi (unbekannte) XML Dateien zusammenführen bzw. mergen
Thema durchsuchen
Ansicht
Themen-Optionen

(unbekannte) XML Dateien zusammenführen bzw. mergen

Ein Thema von padavan · begonnen am 22. Sep 2009 · letzter Beitrag vom 24. Sep 2009
Antwort Antwort
Seite 1 von 3  1 23      
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#1

(unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 22. Sep 2009, 09:06
Hallo,

Wie kann ich zwei mir unbekannte XML-Dateien zusammenführen (mergen)?
(Abgesehen vom Root-Knoten, der heißt immer gleich. Spielt vielleicht eine Rolle für den ein oder anderen Lösungsansatz)

Hier gibt es ein Beispiel von Microsoft, habe Versucht es auf Delphi um zu schreiben, aber es will nicht funktionieren.

Delphi-Quellcode:
procedure XMLmergeBasefileWithAnotherFile(aBaseXMLfile: string; aAnotherXMLfile: string; aTargetFile: string);
var
  XmldocBase : DOMDocument;
  RootBase : IXMLDOMNode;
  NodeBase : IXMLDOMNode;
  ListBase : IXMLDOMNodeList;

  XmldocAnother : DOMDocument;
  RootAnother : IXMLDOMNode;
  NodeAnother : IXMLDOMNode;
  ListAnother : IXMLDOMNodeList;

  i, j : integer;
begin



  // -- Base file laden --
  XmlDocBase := CoDOMDocument.Create;
  if not xmlDocBase.load(aBaseXMLfile) then exit;
  RootBase := XmlDocBase.documentElement;
  ListBase := RootBase.childNodes;

  // -- Another file laden --
  XmldocAnother := CoDOMDocument.Create;
  if not XmldocAnother.load(aAnotherXMLfile) then exit;
  RootAnother := XmlDocBase.documentElement;
  ListAnother := RootAnother.childNodes;


  NodeBase := RootBase.firstChild;
  NodeAnother := RootAnother.firstChild;


  while NodeAnother.NextSibling <> nil do
  begin
    NodeBase.appendChild(NodeAnother);


    NodeAnother := NodeAnother.NextSibling;
  end;



  // -- gemergte Base XML speichern --
  XmldocBase.save(aTargetFile);


end;
Gibt es noch eine andere Möglichkeit?


Ich nutze zur Zeit Delphi 6 Enterprise, mir steht also das TXMLDocument zur Verfügung, und ich habe die MSXML_TLB importiert.

Vielen Dank schon mal

Padavan
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.157 Beiträge
 
Delphi 12 Athens
 
#2

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 22. Sep 2009, 09:38
Delphi-Quellcode:
function XMLmergeBasefileWithAnotherFile(const aBaseXMLfile, aAnotherXMLfile, aTargetFile: String): Boolean;
var
  XmldocBase, XmldocAnother : DOMDocument;
  NodeBase, NodeAnother, NodeNext : IXMLDOMNode;
begin
  Result := False;

  XmlDocBase := CoDOMDocument.Create;
  if not xmlDocBase.load(aBaseXMLfile) then exit;

  XmldocAnother := CoDOMDocument.Create;
  if not XmldocAnother.load(aAnotherXMLfile) then exit;

  NodeBase := XmlDocBase.documentElement;
  NodeAnother := XmldocAnother.documentElement.firstChild;

  while Assigned(NodeAnother) do
  begin
    NodeNext := NodeAnother.NextSibling;
    NodeBase.appendChild(NodeAnother);
    NodeAnother := NodeNext;
  end;

  XmldocBase.save(aTargetFile);
  Result := True;
end;
while NodeAnother.NextSibling <> nil do NodeAnother und nicht NodeAnother.NextSibling, da sonst immer der letze Knoten vergessen würde,
man will ja diesen Knoten einfügen und da ist es nur wichtig, daß dieser existiert ... der nachvolgende ist erstmal egal und wird dann im nächsten Durchgang geprüft

ListBase und ListAnother wurden nie verwendet

Delphi-Quellcode:
NodeBase.appendChild(NodeAnother);
NodeAnother := NodeAnother.NextSibling;
wenn NodeAnother auf das andere Dokument übertragen wurde, hat er keinen Nachfolger mehr, da er er als letzes eingefügt wurde und der "alte" Nachfolger im anderen Dokument verblieb ... also erst den Nachfolger merken und dann den Knoten übertragen

Delphi-Quellcode:
RootAnother := XmlDocBase.documentElement; <<<<<<<<<<<
ListAnother := RootAnother.childNodes;
...
while NodeAnother.NextSibling <> nil do
und daß deine Schleife nie loslief bzw. eine Exception warf, lag auch daran
> RootAnother und XmlDocBase ... fällt dir da was auf?

[edit] die Prozedur noch schnell in eine Funktion umgewandelt
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 22. Sep 2009, 10:37
Wow, Vielen Dank.


Aber vielleicht hätte ich vorher noch genauer sagen sollen, was ich brauche.

Es sollen zwei XML Dateien miteinander verbunden werden, aber, bereits vorhandene Knoten sollen vorhanden bleiben, bzw. bei Änderungen eines "Wertes" geändert werden.

aBaseXMLfile:

Delphi-Quellcode:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert2</Wert>
      </node>
      <node>
         <Kenn>Kennung3</Kenn>
         <Wert>Wert3</Wert>
      </node>
      <node>
         <Kenn>Kennung4</Kenn>
         <Wert>Wert4</Wert>
      </node>
   </nodes>
</root>

aAnotherXMLfile:

Delphi-Quellcode:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert22222222</Wert>
      </node>
      <node>
         <Kenn>Kennung5</Kenn>
         <Wert>Wert5</Wert>
      </node>
   </nodes>
</root>

soll werden zu
aTargetFile:

Delphi-Quellcode:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert> <?bleibt?>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert22222222</Wert> <?wird ueberschrieben?>
      </node>
      <node>
         <Kenn>Kennung3</Kenn> <?bleibt?>
         <Wert>Wert3</Wert>
      </node>
      <node>
         <Kenn>Kennung4</Kenn> <?bleibt?>
         <Wert>Wert4</Wert>
      </node>
      <node>
         <Kenn>Kennung5</Kenn> <?wurde hinzugefuegt?>
         <Wert>Wert5</Wert>
      </node>
   </nodes>
</root>
Bei der von Microsoft angesetzen Lösung (und von himitsu umgesetzen Lösung) werden die Unterknoten nicht berücksichtigt, sondern einfach neue angelegt.
Ich hatte das aber auf der Microsoftseite so verstanden, dass es genau dieses können soll. Ok, dass Beispiel war nicht in der Art gestalltet.

Geht das denn überhaupt?

Edit:
Beim drübernachdenken kommt mir, dass die XML Dateien dann nicht unbekannt sein dürfen. Z.B. der Unterkenner "Kenn" müsste ja bekannt sein, damit die Parameter zugordnet werden können.
Obwohl, wenn man innerhalb der Schleife eine rekursive Unterschleife einbaut, sollte man auch unbekannte Unterknoten herausfinden....jetz bin ich raus
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.157 Beiträge
 
Delphi 12 Athens
 
#4

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 22. Sep 2009, 11:12
Jupp, da muß der Aufbau schon bekannt sein.

Also du gehst Another wie bekannt durch, holst dir jeweils den Inhalt des untergeordneten Kenn
und nun mußt du schauen ob in Base ein Knoten mir Kenn={Text} vorhanden ist,

- wenn ja
inhalt dieses Knotens in Another löschen und den Inhalt von Base rüberkopieren
oder knoten ganz löschen und dann das Selbe wie in "nein" machen

- wenn nein
neuen Knoten erstellen und Inhalt kopieren
oder Knoten wie vorhin einfach übertragen
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 22. Sep 2009, 14:29
Zitat:
- wenn nein
neuen Knoten erstellen und Inhalt kopieren
oder Knoten wie vorhin einfach übertragen
Zitat:
oder Knoten wie vorhin einfach übertragen
Ne, das geht leider nicht, da das Ergebniss von der bisherigen Routine dieses Ergebniss bringt:

Delphi-Quellcode:
<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert2</Wert>
      </node>
      <node>
         <Kenn>Kennung3</Kenn>
         <Wert>Wert3</Wert>
      </node>
      <node>
         <Kenn>Kennung4</Kenn>
         <Wert>Wert4</Wert>
      </node>
   </nodes>
   <nodes> <?dieser sollte eigentlich nicht mehr angelegt werden?>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert22222222</Wert>
      </node>
      <node>
         <Kenn>Kennung5</Kenn>
         <Wert>Wert5</Wert>
      </node>
   </nodes>
</root>
Der erste Unterknoten von <root> ist hier <nodes>.
Dieser hätte nicht noch einmal neu angelegt werden sollen, sondern die <node> Knoten hätten in den bestehenden <nodes> Knoten eingefügt werden sollen.

Bin für Anregungen dankbar, probiere aber mal mein Glück....
  Mit Zitat antworten Zitat
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 23. Sep 2009, 14:24
O mann,
ich komm nicht weiter.

Mein erstes Problem ist nocht nicht gelöst, siehe letzten Beitrag. Die Datei wurde nicht nach meiner Vorstellung gemergt.

Da ich gar nicht weitergekommen bin, habe ich sogar den ersten Knoten mit Namen angesprochen. Die Überschrift "(unbekannte) XML...." stimmt dann zwar nicht mehr, aber das wäre nicht unbedingt das Problem.
Delphi-Quellcode:
    if NodeBase.selectSingleNode('nodes/node[Kenn]').firstChild.text
       = NodeAnother.selectSingleNode('nodes/node[Kenn]').firstChild.text
    then
    begin
      // hier fehlt der Geist
    end;

Dann noch eine Frage. Kann man einen Knoten mitsamt seiner Unterknoten kopieren, ohne das ich die Namen der Knoten wissen muss?

Delphi-Quellcode:

kopiere:

      <node>
         <Kenn>Kennung1</Kenn> <?relevantes Erkennungsmerkmal?>
         <Wert>Wert1</Wert>
         ....
      </node>
Hüüülfe
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.157 Beiträge
 
Delphi 12 Athens
 
#7

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 23. Sep 2009, 14:53
Wie um Himmels Willen, wie löscht man bei diesem Ding die alten Nodes?

Aber im Prinzip geht's, auch wenn man via XPath oder so, bestimmt kürzeren Code hinbekommt
Delphi-Quellcode:
function XMLmergeBasefileWithAnotherFile(const aBaseXMLfile, aAnotherXMLfile, aTargetFile: String): Boolean;
var
  XmldocBase, XmldocAnother : DOMDocument;
  NodeBase, NodeAnother, NodeNext : IXMLDOMNode;
  i, i2 : Integer;
begin
  Result := False;

  XmlDocBase := CoDOMDocument.Create;
  if not xmlDocBase.load(aBaseXMLfile) then exit;

  XmldocAnother := CoDOMDocument.Create;
  if not XmldocAnother.load(aAnotherXMLfile) then exit;

  NodeBase := XmlDocBase.documentElement.firstChild;
  NodeAnother := XmldocAnother.documentElement.firstChild.firstChild;

  while Assigned(NodeAnother) do
  begin
    NodeNext := NodeAnother.NextSibling;
    i := 0;
    while (i < NodeBase.childNodes.length)
        and (NodeBase.childNodes[i].firstChild.text
          <> NodeAnother.firstChild.text) do
      Inc(i);
    if i >= NodeBase.childNodes.length then
    begin
      NodeBase.appendChild(NodeAnother);
    //end else begin
    // NodeBase.childNodes[i].childNodes.DeleteAllChilds; <<<<<<<
    // for i2 := 0 to NodeAnother.childNodes.length - 1 do
    // NodeBase.childNodes[i].appendChild(NodeAnother.childNodes[0]);
    end;
    NodeAnother := NodeNext;
  end;

  XmldocBase.save(aTargetFile);
  Result := True;
end;
macht aus dem in Beitrag #3 dieses
XML-Code:
<?xml version="1.0"?>
<root>
  <nodes>
    <node>
      <Kenn>Kennung1</Kenn> << müßte noch gelöscht werden
      <Wert>Wert1</Wert> << müßte noch gelöscht werden
      <Kenn>Kennung1</Kenn>
      <Kenn>Kennung2</Kenn>
    </node>
    <node>
      <Kenn>Kennung2</Kenn> << müßte noch gelöscht werden
      <Wert>Wert2</Wert> << müßte noch gelöscht werden
      <Wert>Wert1</Wert>
      <Wert>Wert22222222</Wert>
    </node>
    <node>
      <Kenn>Kennung3</Kenn>
      <Wert>Wert3</Wert>
    </node>
    <node>
      <Kenn>Kennung4</Kenn>
      <Wert>Wert4</Wert>
    </node>
    <node>
      <Kenn>Kennung5</Kenn>
      <Wert>Wert5</Wert>
    </node>
  </nodes>
</root>
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 23. Sep 2009, 15:44
Vielen Dank himitsu,

das Ergebnis ist nah dran.
Da scheint noch ein kleiner Schleifenfehler inne zu wohnen.

Das kommentierte Ergebnis müsste lauten:

Delphi-Quellcode:
<root>
  <nodes>
    <node>
      <Kenn>Kennung1</Kenn> << müßte noch gelöscht werden << Das stimmt doch
      <Wert>Wert1</Wert> << müßte noch gelöscht werden << Das stimmt doch
      <Kenn>Kennung1</Kenn> << Das ist zuviel
      <Kenn>Kennung2</Kenn> << Das ist zuviel
    </node>
    <node>
      <Kenn>Kennung2</Kenn> << müßte noch gelöscht werden << Das stimmt doch
      <Wert>Wert2</Wert> << müßte noch gelöscht werden
      <Wert>Wert1</Wert> << Das ist zuviel
      <Wert>Wert22222222</Wert> << richtig!!!
    </node>
    <node>
      <Kenn>Kennung3</Kenn>
      <Wert>Wert3</Wert>
    </node>
    <node>
      <Kenn>Kennung4</Kenn>
      <Wert>Wert4</Wert>
    </node>
    <node>
      <Kenn>Kennung5</Kenn>
      <Wert>Wert5</Wert>
    </node>
  </nodes>
</root>




Zitat:
Wie um Himmels Willen, wie löscht man bei diesem Ding die alten Nodes?
ich nehme an mit
      NodeBase.childNodes[i].removeChild(???) Nur einen sinnvollen Parameter hab ich noch nicht gefunden. Delphi schimpft immer das der zu entfernende Knoten ein Untergeordneter Knoten sein müsse.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.157 Beiträge
 
Delphi 12 Athens
 
#9

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 23. Sep 2009, 15:54
OK, wenn dem so ist, dann laß mal hierbei
Delphi-Quellcode:
if i >= NodeBase.childNodes.length then
begin
  NodeBase.appendChild(NodeAnother);
end else begin
  NodeBase.childNodes[i].childNodes.DeleteAllChilds; <<<<<<<
  for i := 0 to NodeAnother.childNodes.length - 1 do
    NodeBase.childNodes[i].appendChild(NodeAnother.childNodes[0]);
end;
den Else-Zweig weg ... ich glaub dann stimmts

[edit]
warte mal, ich glaub da stimmt was mit den Indize nicht

[edit2]
OK, da in der For.Schleife stimmte der Index nicht FOR i2 und nicht FOR i ,
aber egal, das würde ja nun eh verschwinden ... hab's oben im Post #7 mal editiert
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
padavan

Registriert seit: 12. Jan 2005
271 Beiträge
 
Delphi 7 Enterprise
 
#10

Re: (unbekannte) XML Dateien zusammenführen bzw. mergen

  Alt 23. Sep 2009, 16:13
ach das mit I2 wollte ich auch gerade schreiben.

Aber, den elsezweig ausklammern ist nicht richtig, genau der macht das richtige. Du hast schon recht, es fehlt nur noch das löschen der vorhandenen alten childnodes.

Das Ergebnis Deiner korrigierten Routine ist jetzt

Delphi-Quellcode:
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn> << raus, dann stimmts
         <Wert>Wert1</Wert> << raus, dann stimmts
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn> << raus, dann stimmts
         <Wert>Wert2</Wert> << raus, dann stimmts
         <Kenn>Kennung2</Kenn>
         <Wert>Wert22222222</Wert>
      </node>
      <node>
         <Kenn>Kennung3</Kenn>
         <Wert>Wert3</Wert>
      </node>
      <node>
         <Kenn>Kennung4</Kenn>
         <Wert>Wert4</Wert>
      </node>
      <node>
         <Kenn>Kennung5</Kenn>
         <Wert>Wert5</Wert>
      </node>
   </nodes>
</root>
Fehlt also nur noch das Löschen, dann sollte es stimmen.

mit Pfusch
Delphi-Quellcode:
  while Assigned(NodeAnother) do
  begin
    NodeNext := NodeAnother.NextSibling;
    i := 0;
    while (i < NodeBase.childNodes.length)
        and (NodeBase.childNodes[i].firstChild.text
          <> NodeAnother.firstChild.text) do
      Inc(i);
    if i >= NodeBase.childNodes.length then
    begin
      NodeBase.appendChild(NodeAnother);
    end else begin
// NodeBase.childNodes[i].childNodes.DeleteAllChilds; <<<<<<<
      NodeBase.childNodes[i].removeChild(NodeBase.childNodes[i].firstChild);
      NodeBase.childNodes[i].removeChild(NodeBase.childNodes[i].firstChild);


      for i2 := 0 to NodeAnother.childNodes.length - 1 do
        NodeBase.childNodes[i].appendChild(NodeAnother.childNodes[0]);
    end;
    NodeAnother := NodeNext;
  end;
edit: hier stimmt doch was nicht, da i2 gar nicht in der Schleife vorkommt...

Kommt das richtige Ergebnis:
Delphi-Quellcode:
<root>
   <nodes>
      <node>
         <Kenn>Kennung1</Kenn>
         <Wert>Wert1</Wert>
      </node>
      <node>
         <Kenn>Kennung2</Kenn>
         <Wert>Wert22222222</Wert>
      </node>
      <node>
         <Kenn>Kennung3</Kenn>
         <Wert>Wert3</Wert>
      </node>
      <node>
         <Kenn>Kennung4</Kenn>
         <Wert>Wert4</Wert>
      </node>
      <node>
         <Kenn>Kennung5</Kenn>
         <Wert>Wert5</Wert>
      </node>
   </nodes>
</root>
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz