I have an XSLT 1.0* style sheet which does some pre-processing and creates a result fragment consisting of a list of elements <x>
, each of which has two children - let's call then <a>
and <b>
.
So the generated list looks like:
<x><a>A-content</a><b>B-content</b></x>
<x><a>A-content</a><b>B-content</b></x>
...
<x><a>A-content</a><b>B-content</b></x>
I then convert this into a node set using node-set() and use apply-templates to convert all the <x>
elements to the output representation.
So far, so good.
But I have to use a match="*"
rule on the output template, and although I can get the child elements using "*[1]"
and "*[2]"
, I cannot find them using "a"
and "b"
- I just get an empty result.
The positional syntax works as a workaround, but it's rather fragile and I would like to change it back to working on the element names. Also, it's not very readable.
I did suspect that it might be a namespace problem (<x>
, <a>
and <b>
are not defined in the original schema for the input or output documents), but as far as I can see there is no namespace decoration when the elements are selected using "*".
Just in case it's important, I am using xsltproc under cygwin (libxml 20902, libxslt 10128 and libexslt 817).
Any ideas on what I might be doing wrong, or tips on debugging?
(*- I have to use XSLT 1.0 because it's designed to run in a web browser.)
EDIT: Added examples, as requested
Input test.xml:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="test.xsl" type="text/xsl" ?>
<books>
<book>
<title>Diaspora</title>
<author>Greg Egan</author>
</book>
<book>
<title>2001</title>
<author>Arthur C Clarke</author>
</book>
<book>
<title>Eon</title>
<author>Greg Bear</author>
</book>
</books>
Transform test.xslt:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:exslt="http://exslt.org/common"
xmlns:xalan="http://xml.apache.org/xalan"
xmlns:msxslt="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="xsl msxslt exslt xalan">
<!-- extension-element-prefixes="exslt"> -->
<xsl:template match="books">
<!-- Generate list -->
<xsl:variable name="list">
<xsl:apply-templates select="book" mode="phase1"/>
</xsl:variable>
<html>
<head>
<title>Books</title>
</head>
<body>
<xsl:choose>
<xsl:when test="function-available('msxslt:node-set')">
<xsl:apply-templates select="msxslt:node-set($list)" mode="process-list"/>
</xsl:when>
<xsl:when test="function-available('exslt:node-set')">
<xsl:apply-templates select="exslt:node-set($list)" mode="process-list"/>
</xsl:when>
<xsl:when test="function-available('xalan:nodeset')">
<xsl:apply-templates select="xalan:nodeset($list)" mode="process-list"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="$list" mode="process-list"/>
</xsl:otherwise>
</xsl:choose>
</body>
</html>
</xsl:template>
<xsl:template match="book" mode="phase1">
<!-- Actual transformation is more involved -->
<xsl:element name="x">
<xsl:element name="a">
<b>
<xsl:value-of select="author/text()"/>
</b>
</xsl:element>
<xsl:element name="b">
<i>
<xsl:value-of select="title/text()"/>
</i>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="process-list">
<p>
[<xsl:value-of select="*[1]"/>]
[<xsl:value-of select="*[2]"/>]
[<xsl:value-of select="a"/>]
[<xsl:value-of select="b"/>]
</p>
</xsl:template>
</xsl:stylesheet>
Output (same output from both msxslt and xsltproc):
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Books</title></head>
<body>
<p>
[Greg Egan]
[Diaspora]
[]
[]
</p><p>
[Arthur C Clarke]
[2001]
[]
[]
</p><p>
[Greg Bear]
[Eon]
[]
[]
</p>
</body>
</html>
I can only assume, you are using exslt extension to create nodeset, and i guess you are trying to set up a multi-pass conversion: