Forum Moderators: open
Source XML:
<?xml version="1.0"?>
<submission>
<album>
<track>
<contributor reference="12345">
<role>Writer</role>
</contributor>
<contributor reference="6789">
<role>Composer</role>
</contributor>
</track>
<track>
<contributor reference="12345">
<role>Composer</role>
</contributor>
<contributor reference="6789">
<role>Writer</role>
</contributor>
</track>
</album>
<contributor id="12345">
<name>Willy</name>
</contributor>
<contributor id="6789">
<name>Bob Sapp</name>
</contributor>
</submission>
Our code which we want to get the 'composer' attribute completed with the Contributors name from each track/contributor/role that is a 'Composer'.
<?xml version="1.0"?>
<document>
<release>
<track-list>
<track composer="" />
<track composer="" />
</track-list>
</release>
</document>
and finally the XSLT that i have tried to implement
<?xml version='2.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<document>
<release>
<track-list>
<track>
<xsl:attribute name="composer">
<xsl:if test="a:contributor/a:role = 'Composer'">
<xsl:value-of select="../../a:contributor [a:contributor/@reference = ../../a:contributor/@id]/a:name">
</xsl:value-of>
</xsl:if>
</xsl:attribute>
</track>
</track-list>
</release>
</document>
</xsl:template>
</xsl:stylesheet>
Im trying to get the Composers name for each track after it has checked against the refering number for the composers name on the bottom of the xml..........
Any ideas of where ive gone wrong?
a) figure out how to get your posted XML indented properly.
b) cut and paste your sample and run it to make sure it's not completely bogus (since you're essentially asking others to cut and paste and run it). My XSLT processor is unaware of any XML version "1.0", and I have to clean up your "a:" namespace references to get the samples to run -- something you could have done.
You have a match for a node called "/". That's the root node. The current node will be "/" when that template is invoked. Inside that template, you have a select that refers to "../../contributor", which would then be a reference to nodes higher than the root node, which makes no sense. It looks like you thought XSLT would automagically switch the current node to whichever one you expressed an interest in in your xsl:if. It don't.
However, the xsl:for-each construct does switch the current node to different nodes. You then also need to know how to refer to the current node from a predicate, which is via the "current()" function. If you don't have a copy of a Michael Kay book on XSLT, run right out and get one.
we want to get the 'composer' attribute completed with the Contributors name from each track/contributor/role that is a 'Composer'.
Couldn't figure out that description -- usually people post a sample of what they want the XSLT-produced XML to look like from the given input.
Here's my stab at guessing what you wanted:
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:template match="/">
<document>
<release>
<track-list>
<xsl:for-each select="//track">
<track>
<xsl:attribute name="composer">
<xsl:value-of select="../../contributor[@id=current()/contributor[role='Composer']/@reference]/name"/>
</xsl:attribute>
</track>
</xsl:for-each>
</track-list>
</release>
</document>
</xsl:template>
</xsl:stylesheet> Given your input file, typing this command:
xsltproc foo.xslt foo.xml
produced this:
<?xml version="1.0"?>
<document>
<release>
<track-list>
<track composer="Bob Sapp"/>
<track composer="Willy"/>
</track-list>
</release>
</document>