Reputation:
I am trying to combine two XML documents, one is a list of movies and the other is a list of directors. they look like this. directors
<directors>
<director>
<name>director 1</name>
<born> 5/12/1992 </born>
<nationality>Italian</nationality>
<biography>some info on director</biography>
</director>
<director>
<name>director 2 </name>
<born>21/2/1980</born>
<nationality>french</nationality>
<biography>a bit about me</biography>
</director>
movies
<movies>
<movie>
<title> movie1</title>
<director> director 1 </director>
<date> 1/2/2010 </date>
<genre> Action</genre>
</movie>
<movie>
<title> movie2</title>
<director> director 1 </director>
<date> 1/2/2010 </date>
<genre> romance</genre>
</movie>
<movie>
<title> movie3</title>
<director> director 2 </director>
<date> 1/2/2010 </date>
<genre> Action</genre>
</movie>
and i want to make the output
<director>
<name>director 1</name>
<born> 5/12/1992 </born>
<nationality>Italian</nationality>
<biography>some info on director</biography>
<movies genre="action">
<movie>
<title> movie1</title>
<date> 1/2/2010 </date>
</movie>
<movie>
<title> movie2</title>
<date> 1/2/2010 </date>
</movie>
<movies genre="romance">
<movie>
<title> movie1</title>
<date> 1/2/2010 </date>
</movie>
<movie>
<title> movie2</title>
<date> 1/2/2010 </date>
</movie>
add movies that each director made, grouped by genre.
Upvotes: 0
Views: 105
Reputation: 1645
This is rather simple, let's assume you have an XML directors.xml:
<directors>
<director>
<name>director 1</name>
<born> 5/12/1992 </born>
<nationality>Italian</nationality>
<biography>some info on director</biography>
</director>
<director>
<name>director 2</name>
<born>21/2/1980</born>
<nationality>french</nationality>
<biography>a bit about me</biography>
</director>
</directors>
and an XML movies.xml:
<movies>
<movie>
<title>movie1</title>
<director> director 1 </director>
<date> 1/2/2010 </date>
<genre> Action</genre>
</movie>
<movie>
<title>movie2</title>
<director>director 1</director>
<date> 1/2/2010 </date>
<genre> romance</genre>
</movie>
<movie>
<title> movie3</title>
<director> director 2</director>
<date> 1/2/2010 </date>
<genre> Action</genre>
</movie>
</movies>
If you transform directors.xml with the following XSL Stylesheet, assuming movies.xml is in the same directory as the Stylesheet, you get your desired Output:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="movies-by-genre" match="movie" use="genre"/>
<xsl:template match="directors">
<directors>
<xsl:apply-templates select="director"/>
</directors>
</xsl:template>
<xsl:template match="director">
<xsl:variable name="name" select="normalize-space(name)"/>
<xsl:copy>
<xsl:copy-of select="*"/>
<xsl:for-each
select="document('movies.xml')//movie
[count(. | key('movies-by-genre',genre)[1]) = 1]">
<xsl:if test="key('movies-by-genre',genre)[normalize-space(director)=$name]">
<movies genre="{genre}">
<xsl:for-each select="key('movies-by-genre',genre)">
<xsl:if test="normalize-space(director)=$name">
<xsl:apply-templates select="."/>
</xsl:if>
</xsl:for-each>
</movies>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="movie">
<movie>
<xsl:copy-of select="title | date"/>
</movie>
</xsl:template>
</xsl:stylesheet>
You could also move the filename/path of movies.xml to a parameter and control that from your transformation arguments if you need to be more flexible.
Upvotes: 1