Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Merge two XML files 1

Status
Not open for further replies.

abs2003

MIS
Aug 31, 2004
80
0
0
US
I have two XML files...

Code:
<BookList>
  <Course Name="History 100" />  
</BookList>

and

Code:
<Search>
 <SearchResult>
  <PageNumber>1</PageNumber> 
  <RecordsPerPage>10</RecordsPerPage> 
  <TotalRecords>2</TotalRecords> 
  <ItemNumber>000007U</ItemNumber> 
  <ISBN>0205092403</ISBN> 
  <Description>AMERICAN HISTORY (H)</Description> 
  <Grade>MIHI</Grade> 
  <Copyright>79</Copyright> 
  <Publisher>Prentice Hall Pearson Education</Publisher> 
  <Category>HISTORY</Category> 
  <ListPrice>23.41000</ListPrice> 
  <YourPrice>14.75</YourPrice> 
  <QuantityAvailable>1</QuantityAvailable> 
 </SearchResult>
 <SearchResult>
  <PageNumber>1</PageNumber> 
  <RecordsPerPage>10</RecordsPerPage> 
  <TotalRecords>2</TotalRecords> 
  <ItemNumber>003296U</ItemNumber> 
  <ISBN>0205092594</ISBN> 
  <Description>AMERICAN HISTORY (H)</Description> 
  <Grade>HIGH</Grade> 
  <Copyright>83</Copyright> 
  <Publisher>Prentice Hall Pearson Education</Publisher> 
  <Category>HISTORY</Category> 
  <ListPrice>44.47000</ListPrice> 
  <YourPrice>18.25</YourPrice> 
  <QuantityAvailable>1</QuantityAvailable> 
 </SearchResult>
</Search>

Now I want to merge the two in such...
Code:
<Course Name="History 100">
 <SearchResult>
  <PageNumber>1</PageNumber> 
  <RecordsPerPage>10</RecordsPerPage> 
  <TotalRecords>2</TotalRecords> 
  <ItemNumber>000007U</ItemNumber> 
  <ISBN>0205092403</ISBN> 
  <Description>AMERICAN HISTORY (H)</Description> 
  <Grade>MIHI</Grade> 
  <Copyright>79</Copyright> 
  <Publisher>Prentice Hall Pearson Education</Publisher> 
  <Category>HISTORY</Category> 
  <ListPrice>23.41000</ListPrice> 
  <YourPrice>14.75</YourPrice> 
  <QuantityAvailable>1</QuantityAvailable> 
 </SearchResult>
 <SearchResult>
  <PageNumber>1</PageNumber> 
  <RecordsPerPage>10</RecordsPerPage> 
  <TotalRecords>2</TotalRecords> 
  <ItemNumber>003296U</ItemNumber> 
  <ISBN>0205092594</ISBN> 
  <Description>AMERICAN HISTORY (H)</Description> 
  <Grade>HIGH</Grade> 
  <Copyright>83</Copyright> 
  <Publisher>Prentice Hall Pearson Education</Publisher> 
  <Category>HISTORY</Category> 
  <ListPrice>44.47000</ListPrice> 
  <YourPrice>18.25</YourPrice> 
  <QuantityAvailable>1</QuantityAvailable> 
 </SearchResult>
</Course>

Any idea?

Thank you,
 
In a scripting or programming-language you could use MSxml.DomDocument to copy nodes.
Using XSL you could use the document() function to access another xml-file.
 
jel,

Thank you for responding. I so ignorance with this. Can you provide sample code or point me to the right direction?

 
Here is the dom version:
Code:
[b]'Create 3 DOM objects:[/b]
  Set Dom1 = CreateObject("MSxml.DomDocument")
  Set Dom2 = CreateObject("MSxml.DomDocument")
  Set Dom3 = CreateObject("MSxml.DomDocument")
  Dom1.async = False
  Dom2.async = False

[b]'Load the 2 files:[/b]
  Dom1.Load "File1.xml"
  Dom2.Load "File2.xml"

[b]'Copy the "Course" node of the 1st DOM, as the root node of the 3rd[/b]
  Dom3.appendChild Dom1.selectSingleNode("Course").cloneNode(True)

[b]'Copy the "SearchResult" nodes of the 2nd DOM, to the root node of the 3rd[/b]
  For Each elem In Dom3.documentElement.childNodes
    Dom1.documentElement.appendChild elem.cloneNode(True)
  Next

[b]'Save The 3 DOM object as a new file:[/b]
  Dom3.Save "File3.xml"

I'll let someone else handle the XSL version, unless you want to wait a while...

It's basically the same...

Use the <xsl:copy-of> to copy the elements and child nodes
As jel stated: use the document() to get the element(s) from the second document...
<xsl:for-each> to loop through the "SearchResult" elements...

Nothing to it...

Visit My Site
PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Its not clear what you are trying to achieve. If you just want to do that, why not use notepad? If you want something else, you'll need to specify a bit more information.

Saying that, one way of doing it would be XSL:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:template match="/">
    <xsl:element name="{local-name(document('booklist.xml')/BookList/*)}">
      <xsl:attribute name="{local-name(document('booklist.xml')/BookList/*/@*[1])}">
        <xsl:value-of select="document('booklist.xml')/BookList/*/@*[1]"/>
      </xsl:attribute>
      <xsl:copy-of select="*"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Jon

"There are 10 types of people in the world... those who understand binary and those who don't.
 
JontyMC said:
Its not clear what you are trying to achieve. If you just want to do that, why not use notepad? If you want something else, you'll need to specify a bit more information.

True

That was my first thought, on the other hand, I can see a senario where you have hundreds of files that you want to merge...

Using the DOM method I provided, you could set up a script to merge a list of files instead of one at a time...

Which is also why I touched on XSL, but did not go deep into the details...

Using XSL for external files would require either...
A) A seperate file for each conversion with the second file hardcoded into the document() function.
B) The file name included into the first file with a generic XSL, to tell the document() what to load.
...or...
C) A third file, with both target files included to use in 2 document() functions with a generic XSL

In any of the above cases, it would be more efficient to just use notepad, since you would be modifying the files anyway...

Hence the DOM example provided...

If you have VB, you could set up 2 list boxes, and use a CommonDialog with multi file select enabled to select a list of files to convert...

Even if you just have excel, you could through the same code into a macro, and execute it on the cell, being a 2 column list of file names...

In both cases, you could either have the 3rd file name generated automatically based on a counter or one of the other file names, or add a third row for a custom file name...

This is what the Function would look like:
Code:
[b]Sub MergeFiles(Input1, Input2, Output)[/b]
'Create 3 DOM objects:
  Set Dom1 = CreateObject("MSxml.DomDocument")
  Set Dom2 = CreateObject("MSxml.DomDocument")
  Set Dom3 = CreateObject("MSxml.DomDocument")
  Dom1.async = False
  Dom2.async = False

'Load the 2 files:
  Dom1.Load [b]Input1[/b]
  Dom2.Load [b]Input2[/b]

'Copy the "Course" node of the 1st DOM, as the root node of the 3rd
  Dom3.appendChild Dom1.selectSingleNode("Course").cloneNode(True)

'Copy the "SearchResult" nodes of the 2nd DOM, to the root node of the 3rd
  For Each elem In Dom3.documentElement.childNodes
    Dom1.documentElement.appendChild elem.cloneNode(True)
  Next

'Save The 3 DOM object as a new file:
  Dom3.Save [b]Output[/b]
[b]End Sub[/b]

Then you just plug the names into it, such as:
MergeFiles "File1.xml", "File2.xml", "File3.xml"
Or to write back to one of the other files:
MergeFiles "File1.xml", "File2.xml", "File1.xml"
Would write back to the first

Hope this helps ;-)

Visit My Site
PROGRAMMER: (n) Red-eyed, mumbling mammal capable of conversing with inanimate objects.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top