Reputation: 129
I'm trying to execute a set of given xpaths that are stored in a variable using XSLT 1.0. While accessing the list of xpaths using for-each inside the template, the context changes and thus unable to extract any xpath value from the original xml. It simply returns blank value.
Input xml:
<catalog>
<book id="bk101">
<author>Gambardella Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
</book>
<book id="bk102">
<author>Ralls Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
</book>
</catalog>
XSLT I tried:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="dyn exsl">
<xsl:variable name="newLine" select="'
'" />
<xsl:variable name="comma" select="','" />
<xsl:variable name="details">
<xpaths>
<xpath>/catalog/book/author</xpath>
<xpath>/catalog/book/title</xpath>
<xpath>/catalog/book/genre</xpath>
<xpath>/catalog/book/price</xpath>
<xpath>/catalog/book/publish_date</xpath>
</xpaths>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="*" mode="extract" />
</xsl:template>
<xsl:template match="book" mode="extract">
<xsl:if test="position() !=1">
<xsl:value-of select="$newLine" />
</xsl:if>
<xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
<xsl:if test="position() ! =1" />
<xsl:value-of select="$comma" />
<xsl:variable name="this" select="." />
<xsl:value-of select="dyn:evaluate($this)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The output I'm expecting is:
Gambardella Matthew,XML Developer's Guide,Computer,44.95,2000-10-01
Ralls Kim,Midnight Rain,Fantasy,5.95,,
The output above xslt produces:
,,,,,
,,,,,
Can someone give a clue on the required XSLT 1.0 please? Thank you in advance.
Upvotes: 0
Views: 523
Reputation: 167696
I don't think the absolute XPath expressions you have used make sense in the context of a book
element, you would need to use relative paths. Then you can change the context to the book as follows:
<xsl:variable name="details">
<xpaths>
<xpath>author</xpath>
<xpath>title</xpath>
<xpath>genre</xpath>
<xpath>price</xpath>
<xpath>publish_date</xpath>
</xpaths>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="*" mode="extract" />
</xsl:template>
<xsl:template match="book" mode="extract">
<xsl:if test="position() !=1">
<xsl:value-of select="$newLine" />
</xsl:if>
<xsl:variable name="book" select="."/>
<xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
<xsl:if test="position() != 1">
<xsl:value-of select="$comma" />
</xsl:if>
<xsl:variable name="path" select="." />
<xsl:for-each select="$book"><xsl:value-of select="dyn:evaluate($path)" /></xsl:for-each>
</xsl:for-each>
</xsl:template>
Obviously if you simply use $book/*[local-name() = $path]
you would get it to work without using the usually unsupported dyn:evaluate
.
Upvotes: 1