1
votes

I try to merge two XML files (created with MSword) with the code bellow but although it runs without any error, i receive an error message when i try to open the merged file. Actually the merged file contains the first's file content plus only the first line of the second (the line " < ?xml version="1.0" encoding="UTF-8" standalone="yes" ? > "). No merged contents!

// button select the first file then button2 selects the second and merges them

uses XML.xmlDoc,XML.XMLintf;

var XMLDoc1, XMLDoc2 : TXMLDocument;

procedure TForm30.Button1Click(Sender: TObject);
begin
    if OpenDialog1.Execute then begin
        XMLDoc1 := TXMLDocument.Create(self);
        XMLDoc1.Active := True;
        XMLDoc1.LoadFromFile(OpenDialog1.filename);
    end;
end;

procedure TForm30.Button2Click(Sender: TObject);
var ANode: IXMLNode;
begin
    if OpenDialog1.Execute then begin
        XMLDoc2 := TXMLDocument.Create(self);
        xmlDoc2.Active:= True;
        XMLDoc2.LoadFromFile(OpenDialog1.filename);
        ANode:= XMLDoc2.ChildNodes[0].CloneNode(True);
        xmlDoc1.ChildNodes.add(ANode);
        xmlDoc2.Active:= False;
        xmlDoc1.SaveToFile('c:\' + 'Merge.xml');
        XMLDoc1.free;
        XMLDoc2.free;
        aNode.free;
    end;
end;

What i'm doing wrong, please ? thanks in advance.

1
XML can only have 1 top-level document element, but your code is trying to create 2 top-level elements. Also, you are not taking into account that XMLDoc2.ChildNodes[0] may not be the top-level document element, it could be other node types. In this case, it sounds it is the prolog node. You should use the XMLDoc2.DocumentElement property instead. - Remy Lebeau
thanks Remy, you are right. But I don't know how can I force the two docs to be merged. Any help will be invaluable. - JimPapas

1 Answers

3
votes

XML can only have 1 top-level document element, but your code is trying to create 2 top-level elements.

Also, you are not taking into account that XMLDoc2.ChildNodes[0] may not be the top-level document element. It can be other node types, like processing instructions, etc. In this case, it sounds it is the XML prolog node. To access the top-level element node, use the XMLDoc2.DocumentElement property instead.

If you need to add the second document's top-level element as a child of the first document's top-level element, then try something more like this:

uses
  Xml.XmlDoc, Xml.XmlIntf;

var
  XMLDoc1, XMLDoc2 : IXMLDocument;

procedure TForm30.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then begin
    XMLDoc1 := LoadXMLDocument(OpenDialog1.FileName);
  end;
end;

procedure TForm30.Button2Click(Sender: TObject);
var
  ANode: IXMLNode;
begin
  if OpenDialog1.Execute then begin
    XMLDoc2 := LoadXMLDocument(OpenDialog1.FileName);
    ANode := XMLDoc2.DocumentElement.CloneNode(True);
    XMLDoc1.DocumentElement.ChildNodes.Add(ANode);
    XMLDoc1.SaveToFile('C:\Merge.xml');
    XMLDoc1 := nil;
    XMLDoc2 := nil;
  end;
end;

On the other hand, if you need to preserve both documents' top-level elements, you will have to create a new document with its own top-level element and then add the two documents as its children:

uses
  Xml.XmlDoc, Xml.XmlIntf;

var
  XMLDoc1, XMLDoc2 : IXMLDocument;

procedure TForm30.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then begin
    XMLDoc1 := LoadXMLDocument(OpenDialog1.FileName);
  end;
end;

procedure TForm30.Button2Click(Sender: TObject);
var
  ANode: IXMLNode;
  XMLDoc3: IXMLDocument;
begin
  if OpenDialog1.Execute then begin
    XMLDoc2 := LoadXMLDocument(OpenDialog1.FileName);
    XMLDoc3 := NewXMLDocument;
    ANode := XMLDoc3.AddChild('merged');
    ANode.ChildNodes.Add(XMLDoc1.DocumentElement.CloneNode(True));
    ANode.ChildNodes.Add(XMLDoc2.DocumentElement.CloneNode(True));
    XMLDoc3.SaveToFile('C:\Merge.xml');
    XMLDoc1 := nil;
    XMLDoc2 := nil;
  end;
end;