Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 417
  • Last Modified:

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>



0
scotdance
Asked:
scotdance
1 Solution
 
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
 
atul_parmarCommented:
If mainfile.xml has to be the same as second.xml then simply copy second.xml as mainfile.xml.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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
 
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
 
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

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now