CocaCola
CocaCola

Reputation: 763

Combining 2 XML files into 1 using XSL

I'm having trouble finding a suitable example to merge 2 XML files into 1, as per below:

movies.xml

<movies>
    <movie>
        <name>ET</name>
        <director>Steven Spielberg</director>
        <date>15 January 2000</date>
    </movie>
    <movie>
        <name>The Neverending Story</name>
        <director>Steven Spielberg</director>
        <date>4 November 2006</date>
    </movie>
</movies>

directos.xml

<directors>
    <director>
        <name>Steven Spielberg</name>
        <age>55</age>
        <sex>male</sex>
    </director>
</directors>

required output:

<directors>
    <director>
        <name>Steven Spielberg</name>
        <age>55</age>
        <sex>male</sex>
        <movies>
            <movie>
                <name>ET</name>
                <date>15 January 2000</date>
            </movie>
            <movie>
                <name>The Neverending Story</name>
                <date>4 November 2006</date>
            <movie>
        </movies>
    </director>
</directors>

XSL:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method = "xml" indent = "yes" /> 

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="$movieFile/movies/movie/director">
        <xsl:copy>
            <xsl:apply-templates />
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

At the moment, it is printing the whole director list within each movie group.

Can somebody please give me some guidance?

Upvotes: 3

Views: 1159

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116959

If you can indeed use XSLT 2.0, then this could be quite simple:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

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

<xsl:key name="movie-by-director" match="movie" use="director" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="director">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <movies>
            <xsl:apply-templates select="key('movie-by-director', name, $movieFile)" />
        </movies>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

helderdarocha
helderdarocha

Reputation: 23637

If you replace your second template with this one, and feed the 'directors.xml' file as input it should work:

<xsl:template match="director">
    <xsl:variable name="director-name" select="name"/>
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    <xsl:apply-templates select="document('movies.xml')/movies/movie[director=$director-name]" />
    </xsl:copy>
</xsl:template>

You copy each node using the identity template except the director node above, in which you add the matching contents of the movie file.

Upvotes: 2

Related Questions