The solution to this is a very short and easy conversion (absolutely no extension functions are required!):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/*"> <html> <ul> <xsl:apply-templates select="document(entry)/*/tag"> <xsl:sort/> </xsl:apply-templates> </ul> </html> </xsl:template> <xsl:template match="tag"> <li><xsl:value-of select="."/></li> </xsl:template> </xsl:stylesheet>
when this conversion is applied to the provided index.xml file :
<list> <entry>a.xml</entry> <entry>b.xml</entry> </list>
required, the correct result is obtained :
<html> <ul> <li>aa</li> <li>bb</li> <li>cc</li> <li>xx</li> </ul> </html>
, and it displays in any browser as :
Explanation : This solution uses the power of the standard XSLT document() function. strong> As defined in W3C XSLT 1.0 Recommendation:
When a document function has exactly one argument and the argument is node-set, the result is the union, for each node into the node-set argument, of the result of calling the document function with the first argument - this is the string value of node
This explains the effect of this snippet from our code :
<xsl:apply-templates select="document(entry)/*/tag"> <xsl:sort/> </xsl:apply-templates>
What happens here is that the argument to the document() function is the node-set of all entry children of the top element of index.xml . The result is a union of all document nodes.
therefore
select="document(entry)/*/tag"
selects all tag elements in all documents specified in index.xml . Then they are sorted (via xsl:sort ), and each element of the already sorted nodelist is processed by the template corresponding to the tag .
Dimitre novatchev
source share