Reputation: 71
Is it possible with XSLT 3.0 to transform a string to an element name in a XPATH-query? I would like to pass the name of an element as a string to a template and then include the name of the element in an XPATH-expression. Something like this <xsl:variable name="el-name" select="'p'"/><xsl:copy-of select="$el-name"/>
where el-name
is not a string anymore, but selects the element p.
Let's suppose I have a source document like this:
<?xml version="1.0" encoding="UTF-8"?>
<text xmlns="">
<list xml:id="p-1">
<item n="1"/>
<item n="2"/>
</list>
<head>This is a heading</head>
<p xml:id="p-1">Lorem ipsum</p>
<p xml:id="p-2">dolorosum</p>
</text>
And a stylesheet like this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xpath-default-namespace="" exclude-result-prefixes="xs" xmlns="">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/text">
<selection-of-text xmlns="">
<xsl:call-template name="get-elements">
<xsl:with-param name="element-name" as="xs:string" select="'list'"/>
</xsl:call-template>
<xsl:call-template name="get-elements">
<xsl:with-param name="element-name" as="xs:string" select="'p'"/>
</xsl:call-template>
</selection-of-text>
</xsl:template>
<xsl:template name="get-elements">
<xsl:param name="element-name"/>
<xsl:choose>
<xsl:when test="$element-name = 'list'">
<xsl:copy-of select="list"/>
</xsl:when>
<xsl:when test="$element-name = 'p'">
<xsl:copy-of select="p"/>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
In BASH I run
java -cp "/mnt/c/Tools/SaxonHE9-9-1-4J/saxon9he.jar" net.sf.saxon.Transform \
-s:source.xml -xsl:stylesheet.xslt -o:output.xml
and get the desired output:
<?xml version="1.0" encoding="UTF-8"?>
<selection-of-text>
<list xml:id="p-1">
<item n="1"/>
<item n="2"/>
</list>
<p xml:id="p-1">Lorem ipsum</p>
<p xml:id="p-2">dolorosum</p>
</selection-of-text>
My code works but it is clumsy. I suppose xsl:evaluate
might work to dynamically construct the proper XPATH expression but I don't get how. https://www.w3.org/TR/xslt-30/#evaluate-effect
Upvotes: 0
Views: 1092
Reputation: 71
As Martin Honnen kindly explained above, a simple and short solution is this:
<xsl:template name="get-elements">
<xsl:param name="element-name"/>
<xsl:copy-of select="*[name() = $element-name]"/>
</xsl:template>
An alternative solution, that I tested with Saxon PE 9.9.1.4, is this:
<xsl:template name="get-elements">
<xsl:param name="element-name"/>
<xsl:variable name = "els">
<xsl:evaluate xpath="$element-name" context-item="."/>
</xsl:variable>
<xsl:copy-of select="$els"/>
</xsl:template>
Upvotes: 1