[MSXML3] Dynamic XPATHs
Let's say you want to generate an XPATH using a variable or a value
derived from the document itself. The variable contains the name of an attribute to access.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dyn="http://exslt.org/dynamic"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="dyn msxsl">
<msxsl:script implements-prefix="dyn" language="jscript">
function evaluate(context, expression)
{
return
context.nextNode().selectNodes(expression);
}
</msxsl:script>
...
</xsl:stylesheet>
You could call it with:
<xsl:value-of select="dyn:evaluate(., concat('@', $y))"/>
to get the attribute named the same as the string held in $y on the context node.
I've used the EXSLT namespace here, but you should make up your own.
<Opinion>
What the hell was the XSLT 1.0 spec team thinking? Why isn't this
part of the spec?
</Opinion>
[MSXML3] Dynamic XPATHs II
Let's try a more advanced example, one
that needs to put quotes around a string. Quotes are a
challenge in XPATH statements because you can't put '
in an XPATH expression. It simply doesn't work because the entity gets
resolved when the stylesheet is parsed. My solution is to write an
extension function that returns a single quote and use 'concat'. <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="dyn msxsl">
<xsl:output method="html" />
<msxsl:script implements-prefix="dyn" language="jscript">
function evaluate(context, expression)
{ return context.nextNode().selectNodes(expression); }
function quote() { return "'"; }
</msxsl:script>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="Instances/Instance">
<xsl:if test="@name">
<xsl:choose>
<xsl:when test="dyn:evaluate(., concat('//Step[@*=',
dyn:quote(), @name, dyn:quote(), ']'))" />
<xsl:otherwise>
<xsl:value-of select="@name">
</xsl:value-of>
<br />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This example creates XPATH statements that look like:
//Step[@*='foo']
Where the string foo comes from an attribute in the
document.
Extracting the Last Child from Its Parent and Ancestors
Let's say you want to produce <child id='b'/> from
the following: <Root>
<parent>
<child id='a'/>
<child id='b'/>
</parent>
</Root>
Here's how to do it: <xsl:template
match="parent/child[last()]">
<xsl:copy>
<xsl:copy-of select="@* | * | text()" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
|