Merging two XML files into one

Hi
I need to merge to XML files into one using my app written in Delphi 6.
The main file(mainfile.xml) will be the one that the second
file(secondfile.xml) needs to be merged into.

If an entry does not exist in mainfile.xml that exists in secondfile.xml
then it should be added to mainfile.xml but if the entry exists in both the
files then it is not to be added to mainfile.xml

Samples of the xml files are below.

Thanks for any help

Example of mainfile.xml :
<?xml version="1.0" encoding="utf-8"?>
<languages>
     <langs>
         <lang code="design" name="Design"/>
         <lang code="de" name="Deutsch"/>
     </langs>
     <statics>
         <static id="1">
              <lang code="design" value="Yes"/>
         </static>
         <static id="2">
              <lang code="design" value="No"/>
              <lang code="de" value="Nein"/>
         </statics>
     </statics>
     <dynamics>
         <dynamic id="1">
              <lang code="design" value="Hello"/>
              <lang code="de" value="hallo"/>
         </dynamic>
     </dynamic>
</languages>

Example of second.xml :
<?xml version="1.0" encoding="utf-8"?>
<languages>
     <langs>
         <lang code="design" name="Design"/>
         <lang code="de" name="Deutsch"/>
     </langs>
     <statics>
         <static id="1">
              <lang code="design" value="Yes"/>
              <lang code="de" value="Ja;"/>                         add this
entry to mainfile.xml
         </static>
         <static id="2">
              <lang code="design" value="No"/>
              <lang code="de" value="Nein"/>
         </statics>
     </statics>
     <dynamics>
         <dynamic id="1">
              <lang code="design" value="Hello"/>
              <lang code="de" value="Hallo"/>
         </dynamic>
         <dynamic id="2">
add following entries to mainfile.xml
              <lang code="design" value="Goodbye"/>
              <lang code="de" value="Auf Wiedersehen"/>
         </dynamic>
     </dynamic>
</languages>



scotdanceAsked:
Who is Participating?
 
atul_parmarCommented:
Hi,

It is not typo. it was coded so that nonexisting entry can be added after last found entry. But sure, there was a bug I fixed it. Try this now. and can you explore more with your statement

Another thing it is doing is overwriting the existing values if the value in the secondfile is different, have you any idea as to how to stop this? ?????????????????

var
  sl1, sl2 : TStringList;
  li, lastindex, i : integer;
  mainfile, secondfile, newfile : string;
begin
  sl1 := TStringList.Create;
  sl2 := TStringList.Create;
  mainfile := 'c:\mainfile.xml';
  secondfile := 'c:\second.xml';
  newfile := 'c:\mergedfile.xml';
  sl1.LoadFromFile(mainfile);
  sl2.LoadFromFile(secondfile);
  lastindex := 0;
  for i:= 0 to sl2.Count - 1 do
  begin
    li := sl1.IndexOf(sl2[i]);
    if li =-1 then
    begin
      sl1.Insert(lastindex, sl2[i]);
      inc(lastindex);
    end
    else
      lastindex := li;
  end;
  sl2.SaveToFile(newfile);
  Memo1.Lines.Assign(sl1);
  Memo2.Lines.Assign(sl2);
  sl1.Free;
  sl2.Free;
end;
0
 
atul_parmarCommented:
By looking at both of the files it seems that after merging both should look like the same. Or mainfile.xml can have the values what does not exist in the second.xml ?
0
 
scotdanceAuthor Commented:
Yes
That is what i am after the missing records to be added to the mainfile.xml

Thanks
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
atul_parmarCommented:
If mainfile.xml has to be the same as second.xml then simply copy second.xml as mainfile.xml.
0
 
atul_parmarCommented:
Well, if it is not the case and mainfile can have values what may not exist in the second.xml then use the following code.
It will insert the nonexisting entry to mainfile after the last found entry.

var
  sl1, sl2 : TStringList;
  li, i : integer;
  mainfile, secondfile, newfile : string;
begin
  sl1 := TStringList.Create;
  sl2 := TStringList.Create;
  mainfile := 'mainfile.xml';
  secondfile := 'second.xml';
  newfile := 'mergedfile.xml';
  sl1.LoadFromFile(mainfile);
  sl2.LoadFromFile(secondfile);
  li := 0;
  for i:= 0 to sl2.Count - 1 do
  begin
    li := sl1.IndexOf(sl2[i]);
    if li =-1 then
      sl1.Insert(li, sl2[i]);
  end;
  sl2.SaveToFile(newfile);
  Memo1.Lines.Assign(sl1);
  Memo2.Lines.Assign(sl2);
  sl1.Free;
  sl2.Free;
end;
0
 
scotdanceAuthor Commented:
I cannot copy over the mainfile as the end user will be able to change it,

Thanks i'll give the code a try in the morning.

0
 
scotdanceAuthor Commented:
Hi
just tried that i'm getting a 'List index out of bounds(-1)' error, i've traced it to the if statement in the for loop,

Any ideas how to over come this?
Thanks
0
 
scotdanceAuthor Commented:
Hi
fixed the error I got was a typo

sl1.Insert(li, sl2[I]);

should have read

sl1.Insert(I, sl2[I]);


Another thing it is doing is overwriting the existing values if the value in the secondfile is different, have you any idea as to how to stop this?

Thanks again for the help, been trawling the web all day for an answer, lol
0
 
scotdanceAuthor Commented:
Hi
thanks for that it works good,
the problem I was having with it overwriting existing values in mainfile.xml that have been changed in the secondfile.xml
for example in mainfile.xml I have

<lang code="design" value="Yes"/>

but in the secondfile.xml it has been changed to

<lang code="design" value="Yessss"/>

in the mergedfile.xml it is saving the value from secondfile.xml where I need it to keep the existing value from mainfile.xml,
as the mainfile.xml can be modified by the end user and our secondfile.xml is to be used as an update to the mainfile.xml

Apart from this it works fine,
Thanks again
0
 
atul_parmarCommented:
The above code will NOT overwrite the original entry in the mainfile.xml. So it already fulfills your requirement.

However I can see a typo in mycode sl2.SaveToFile(newfile); as it should be sl1.SaveToFile(newfile); because sl1 contains the mergedrecord.
Now check the content of mergedfile.xml
0
 
scotdanceAuthor Commented:
Hi
The existing value was being overwritten in the mainfile.xml as that was where I was saving my output too, as this will be the only file the user will load into there system.

Also when I made the fix to the save, you just mentioned, it is now seems to be adding this entry out with the first entry, although your existing version seemed to work ok

Example of input files and output file:

mainfile.xml has:

<?xml version="1.0" encoding="utf-8"?>
<languages ControlCount="5" DynamicCount="2" LangCount="7" DefLang="design">
 <controls>
  <control id="1" TextType="Single" LineCount="1">
   <language code="design" value="Yes"/>
  </control>
 </controls>
</languages>

seconfdile.xml has:

<?xml version="1.0" encoding="utf-8"?>
<languages ControlCount="5" DynamicCount="2" LangCount="7" DefLang="design">
 <controls>
  <control id="1" TextType="Single" LineCount="1">
   <language code="design" value="Yessssss"/>
   <language code="de" value="Ja"/>
  </control>
 </controls>
</languages>

output file is as follows with the changed value outside the control:

<?xml version="1.0" encoding="utf-8"?>
<languages ControlCount="5" DynamicCount="2" LangCount="7" DefLang="design">
 <controls>
   <language code="design" value="Yessssss"/>        
  <control id="1" TextType="Single" LineCount="1">
   <language code="design" value="Yes"/>
   <language code="de" value="Ja"/>
  </control>
 </controls>
</languages>
0
 
atul_parmarCommented:
Well, change the sequence of following line from
begin
   sl1.Insert(lastindex, sl2[i]);
   inc(lastindex);
end

to

begin
   inc(lastindex);
   sl1.Insert(lastindex, sl2[i]);
end
0
 
scotdanceAuthor Commented:
we are getting close to the end answer, it's amazing how one little type or line of code in the wrong place can make such a difference, lol

It is now producing the following

  <control id="1" TextType="Single" LineCount="1">
   <language code="design" value="Yessssss"/>
   <language code="de" value="Jaaa"/>
   <language code="design" value="Yes"/>
   <language code="de" value="Ja"/>
  </control>

Am I right in guessing I'll need to check to see the value of code before adding the line incase it already exists?
Thanks
0
 
atul_parmarCommented:
It is not that much easy with TStringList. Or even if you do it, performancewise it will degrade.
0
 
scotdanceAuthor Commented:

Thanks I'll have a play with it and see what i can do.
Is there a way you can recommend to do it? Or i can look at?
Thanks
0
 
Wim ten BrinkSelf-employed developerCommented:
Am just wondering why you'd not be using a much simpler technique like XSLT for this. It wouldn't be too difficult to get a transformation like this done in XSLT and it allows you some interesting flexibility.
The solutions that I see here so far are purely Delphi-related and thus might only work for this single XML sample you provided. When working with XML you should keep in mind that simple string manipulations on the XML are just dirty tricks.
0
 
scotdanceAuthor Commented:
I don't have the time to sit down and learn about XSLT unfortunately, plus we are designing the default file the user will use.
0
 
scotdanceAuthor Commented:
Hi
thanks for your help been testing it out on the final version of my files, and it's adding duplicate lines as i have lines that are being changed in the program that uses the xml file that i  will not know about for the update file.  

So looks like i might need to try the XSLT route after all

0
 
Eddie ShipmanAll-around developerCommented:
See my post here:
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21367431.html

You will have to modify the code to get the algorithm correct for inserting nodes that do not exist
in mainfile.xml but exist in second.xml but it is not difficult.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.