![]() |
(unbekannte) XML Dateien zusammenführen bzw. mergen
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) ![]()
Delphi-Quellcode:
Gibt es noch eine andere Möglichkeit?
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; 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 |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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;
Delphi-Quellcode:
NodeAnother und nicht NodeAnother.NextSibling, da sonst immer der letze Knoten vergessen würde,
while NodeAnother.NextSibling <> nil do
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:
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
NodeBase.appendChild(NodeAnother);
NodeAnother := NodeAnother.NextSibling;
Delphi-Quellcode:
und daß deine Schleife nie loslief bzw. eine Exception warf, lag auch daran
RootAnother := XmlDocBase.documentElement; <<<<<<<<<<<
ListAnother := RootAnother.childNodes; ... while NodeAnother.NextSibling <> nil do > RootAnother und XmlDocBase ... fällt dir da was auf? [edit] die Prozedur noch schnell in eine Funktion umgewandelt :angel2: |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
Wow, Vielen Dank.
Aber vielleicht hätte ich vorher noch genauer sagen sollen, was ich brauche. :oops: 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:
Bei der von Microsoft angesetzen Lösung (und von himitsu umgesetzen Lösung) werden die Unterknoten nicht berücksichtigt, sondern einfach neue angelegt.
<?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> 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 |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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 |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
Zitat:
Zitat:
Delphi-Quellcode:
Der erste Unterknoten von <root> ist hier <nodes>.
<?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> 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.... |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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:
Hüüülfekopiere: <node> <Kenn>Kennung1</Kenn> <?relevantes Erkennungsmerkmal?> <Wert>Wert1</Wert> .... </node> |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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:
macht aus dem in Beitrag #3 dieses
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;
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> |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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:
Delphi-Quellcode:
Nur einen sinnvollen Parameter hab ich noch nicht gefunden. Delphi schimpft immer das der zu entfernende Knoten ein Untergeordneter Knoten sein müsse.
NodeBase.childNodes[i].removeChild(???)
|
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
OK, wenn dem so ist, dann laß mal hierbei
Delphi-Quellcode:
den Else-Zweig weg ... ich glaub dann stimmts
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; [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 :oops: , aber egal, das würde ja nun eh verschwinden ... hab's oben im Post #7 mal editiert |
Re: (unbekannte) XML Dateien zusammenführen bzw. mergen
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:
Fehlt also nur noch das Löschen, dann sollte es stimmen.
<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> mit Pfusch
Delphi-Quellcode:
edit: hier stimmt doch was nicht, da i2 gar nicht in der Schleife vorkommt...
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; 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> |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz