Reputation: 13
I know there have been other questions on this topic, but what I'm looking for its not there.
What I want to do is to combine 2 XML files, but not exactly one XML file after another.
For example my first xml file would be game.xml:
<forSale>
<game>
<title>Mass Effect 3</title>
<releaseDate>
<yyyy>2012</yyyy>
<mm>03</mm>
<dd>06</dd>
</releaseDate>
<esrbRating>M</esrbRating>
<platforms>
<platform>X360</platform>
</platforms>
</game>
<game>
<title>Borderlands 2</title>
<releaseDate>
<yyyy>2012</yyyy>
<mm>09</mm>
<dd>18</dd>
</releaseDate>
<esrbRating>M</esrbRating>
<platforms>
<platform>PC</platform>
</platforms>
</game>
And my second xml file reviews.xml
<reviews>
<game>
<title>Mass Effect 3</title>
<review>
<critic>Kevin VanOrd</critic>
<pros>
<pro><![CDATA[Fantastic, moving story that balances plot and character]]></pro>
</pros>
<cons>
<con><![CDATA[Some glitches and bugs]]></con>
</cons>
</review>
</game>
<game>
<title>Borderlands 2</title>
<review>
<critic>Chris Watters</critic>
<pros>
<pro><![CDATA[A ton of great mission writing and dialogue]]></pro>
</pros>
<cons>
<con><![CDATA[Spoken messages sometimes interrupt each other]]></con>
</cons>
</review>
</game>
And I want my resulting master XML to be like this:
<forSale>
<game>
<title>Mass Effect 3</title>
<releaseDate>
<yyyy>2012</yyyy>
<mm>03</mm>
<dd>06</dd>
</releaseDate>
<esrbRating>M</esrbRating>
<platforms>
<platform>X360</platform>
</platforms>
<review>
<critic>Kevin VanOrd</critic>
<synopsis>
Mass Effect 3 is a remarkably satisfying conclusion to a beloved trilogy, and a poignant and memorable role-playing action game in its own right.
</synopsis>
<pros>
<pro>Fantastic, moving story that balances plot and character</pro>
</pros>
<cons>
<con>Some glitches and bugs</con>
</cons>
</review>
</game>
<game>
<title>Borderlands 2</title>
<releaseDate>
<yyyy>2012</yyyy>
<mm>09</mm>
<dd>18</dd>
</releaseDate>
<esrbRating>M</esrbRating>
<platforms>
<platform>PC</platform>
</platforms>
<review>
<critic>Chris Watters</critic>
<synopsis>
Stellar writing and a host of small improvements help Borderlands 2 stand tall on the shoulders of its predecessor.
</synopsis>
<pros>
<pro>A ton of great mission writing and dialogue</pro>
</pros>
<cons>
<con>Spoken messages sometimes interrupt each other</con>
</cons>
</review>
</game>
I tried this code, but it outputs the games first then the reviews
<xsl:template match="/forSale">
<xsl:copy>
<xsl:apply-templates select="game"/>
<xsl:apply-templates select="document('reviews.xml')/reviews/game/review"/>
</xsl:copy>
</xsl:template>
<xsl:template match =" @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node() | text()"/>
</xsl:copy>
</xsl:template>
Upvotes: 0
Views: 70
Reputation: 70648
This is because this line...
<xsl:apply-templates select="document('reviews.xml')/reviews/game/review"/>
is independent from the previous line where you select the games, and so will copy all games, not just a specific line.
What you need to do is more this line into a template that matches the game element, and amend it to output the selected game only
<xsl:apply-templates select="document('reviews.xml')/reviews/game[title=current()/title]/review"/>
Try this XSLT
<xsl:template match="/forSale">
<xsl:copy>
<xsl:apply-templates select="game"/>
</xsl:copy>
</xsl:template>
<xsl:template match="game">
<xsl:copy>
<xsl:apply-templates select="@* | node() | text()"/>
<xsl:apply-templates select="document('reviews.xml')/reviews/game[title=current()/title]/review"/>
</xsl:copy>
</xsl:template>
<xsl:template match =" @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node() | text()"/>
</xsl:copy>
</xsl:template>
Upvotes: 1