Re: [xsl] Joining two XML-files

Subject: Re: [xsl] Joining two XML-files
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Sat, 20 Oct 2001 15:09:39 +0100
Hi Jorge,

> These files are related through the commom value of an attribute. In
> the previous example file1.att1 is found in file2.fld1 I need to
> produce a third file where get mixed some attributes of the related
> "records".For example:
>
> file3.xml
>     <row att1='foo' att2='morefoo" fld2='otherfoo" />
>     <row att1='foo2' att2='morefoo2" fld2='otherfoo2" />
>     <row att1='foo2' att2='morefoo2" fld2='anotherfoo2" />
> ...
> </data>

Whenever you're dealing with multiple input files, you should create a
global variable to hold their root nodes, so you can swap between them
easily. For example:

<xsl:variable name="file1" select="document('file1.xml')" />
<xsl:variable name="file2" select="document('file2.xml')" />

Whenever you're trying to get quick access to a node based on some
property of that node (such as getting a row element according to the
value of its fld1 attribute), you should set up a key that indexes
those nodes by that property. For example:

<xsl:key name="rows-by-fld1" match="row" use="@fld1" />

Now, you need to work through the rows in file1.xml. For each row, you
need to copy the row with its attributes from file1.xml:

<xsl:template match="/">
  <data>
    <xsl:for-each select="$file1/data/row">
      <xsl:copy>
        <xsl:copy-of select="@*" />
        ...
      </xsl:copy>
    </xsl:for-each>
  </data>
</xsl:template>

Then you need to add the attributes from file2.xml. You need to
quickly get the row that has the same value in its fld1 attribute
as the current row from file1.xml has in its att1 attribute. You can
put this value in a variable for safe keeping, and to use the key on
file2.xml, you need to change the context to this file (which you can
do with xsl:for-each). Use the key to get hold of the relevant row,
and then copy all the attributes aside from the @fld1 attribute:

  <xsl:for-each select="$file1/data/row">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:variable name="att1" select="@att1" />
      <xsl:for-each select="$file2">
        <xsl:copy-of select="key('rows-by-fld1', $att1)
                               /@*[name() != 'fld1']" />
      </xsl:for-each>
    </xsl:copy>
  </xsl:for-each>

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread