Reputation: 21
I have XML similar to below. I want to "recordize", if you will, the xml based on the authors. So for each author child node I want a complete copy of all the xml and just one author child node for each copy. I have gotten close but generate the authors correctly is hanging me up. Any help is appreciated!
SAMPLE:
<root>
<book>
<name>
... some data
</name>
<info>
... some data
</info>
<authors>
<author> Author 1</author>
<author> Author 2</author>
</authors>
other nodes
.
</book>
</root>
=======================
OUTPUT:
<root>
<book>
<name>
... some data
</name>
<info>
... some data
</info>
<authors>
<author>Author 1</author>
</authors>
other nodes
.
</book>
</root>
<root>
<book>
<name>
... some data
</name>
<info>
... some data
</info>
<authors>
<author>Author 2</author>
</authors>
other nodes
.
</book>
</root>
Upvotes: 1
Views: 63
Reputation: 116972
This is not exactly trivial - try:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="book/authors/author">
<xsl:apply-templates select="ancestor::book">
<xsl:with-param name="author" select="."/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:param name="author"/>
<xsl:copy>
<xsl:apply-templates select="node()">
<xsl:with-param name="author" select="$author"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="author">
<xsl:param name="author"/>
<xsl:if test=".=$author">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Note: if you can use a XSLT 2.0 processor, read up on parameter tunneling; that will make this slightly less complicated.
Upvotes: 1