I want to have a key value map in xsl and so defined a variable which has an xml fragment, but later when I try to access the xml nodes in the variable I get an error that type of the xpath xpression cannot be resolved.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:variable name="map"> <map> <entry key="key-1">value1</entry> <entry key="key-2">value2</entry> <entry key="key-3">value3</entry> </map> </xsl:variable> <output> <xsl:value-of select="$map/entry[@key='key-1']"/> </output> </xsl:template> </xsl:stylesheet>
Use. Interface descriptions are in the form of XML documents. XSL Transformation (XSLT) is a member of the XML family of languages. It describes how one XML structure is transformed into another XML structure.
You can call any of the MarkLogic Server Built-In XQuery functions from an XSLT stylesheet.
XSL Transformation (XSLT)XSLT is designed to be used as part of XSL. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.
Using XSLT 2.0, the following solution works:
<xsl:variable name="map"> <entry key="key-1">value1</entry> <entry key="key-2">value2</entry> <entry key="key-3">value3</entry> </xsl:variable> <xsl:template match="/"> <output> <xsl:value-of select="$map/entry[@key='key-1']"/> </output> </xsl:template>
You cannot use a result tree fragment in a XPath expression in XSLT 1.0, but fn:document()
can retrieve map values. An answer to a similar question will work here:.
<xsl:value-of select="document('')//xsl:variable[@name='map']/map/entry[@key='key-1']"/>
As described in the XSLT 1.0 specification:
document('')
refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document.
However, you don't need to use xsl:variable
for this. You could specify your map node directly under xsl:stylesheet
, but you must remember that a top level elements must have a non null namespace URI:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="some.uri" exclude-result-prefixes="my"> <my:map> <entry key="key-1">value1</entry> <entry key="key-2">value2</entry> <entry key="key-3">value3</entry> </my:map> <xsl:template match="/"> <output> <xsl:value-of select="document('')/*/my:map/entry[@key='key-1']"/> </output> </xsl:template> </xsl:stylesheet>
You can sort of work around XSLT 1.0 missing support for using the variable's contents as a node set. You'll have to rely on extensions added by the parser's maker. For example, Microsoft has offered a function to work around this: node-set()
Your XSL will look like this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <xsl:template match="/"> <xsl:variable name="map"> <map> <entry key="key-1">value1</entry> <entry key="key-2">value2</entry> <entry key="key-3">value3</entry> </map> </xsl:variable> <output> <xsl:value-of select="msxsl:node-set($map)/map/entry[@key='key-1']"/> </output> </xsl:template> </xsl:stylesheet>
Notice the namespace and the msxsl-prefix here. This will only work in applications based on Microsoft's parser (for example: Internet Explorer utilizes it, as well as .NET). Other parsers may or may not have such an extension (Saxxon does, for example, but it's named a bit differently). But, it eliminates depending on XSLT 2.0, as this will work fine in XSLT 1.0 and Microsoft has yet to support XSLT 2.0 in their XML library (unless they've added it recently).
Depending on the parser you're using, the above may work fine for you, otherwise Per T's answer is better for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With