Nothing returned for element name (XSL/XPath)
I have code that I expect to return the element name, but nothing is returned.
The following code is from an XSL doc that generates another XSL 开发者_运维知识库doc.. where $expression is a variable that dynamically created an XPath expression.
<xsl:template match="/">
...
<xslt:template match="{$expression}">
<elem key="{name()}">
<xslt:copy-of select="@*"/>
<xslt:for-each select="@*">
<xslt:sort select="name()"/>
<attribute>|<xslt:value-of select="name()"/>|</attribute>
</xslt:for-each>
</elem>
</xslt:template>
...
</xsl:template>
That code then generates the second XSL doc with this code.. notice how @key is blank.
<xsl:template match="//*[@name='Spot']">
<elem key="">
<xsl:copy-of select="@*" />
<xsl:for-each select="@*">
<xsl:sort select="name()" />
<attribute>|<xsl:value-of select="name()" />|</attribute>
</xsl:for-each>
</elem>
</xsl:template>
Besides the @key being blank, everything works as expected. My only problem is displaying the name of the element.
EDIT: To clarify what I'm actually looking for, I need the names of the elements from the results returned by <xslt:template match="{$expression}">
.
Thanks! :)
Because your transformation is producing itself XSLT code and you want to have in the result:
<elem key="{name()}">
you must escape the {
and }
, so that the AVT is not evaluated immediately.
Producing {
and }
as-is is done by doubling them as specified in the XSLT spec:
"When an attribute value template is instantiated, a double left or right curly brace outside an expression will be replaced by a single curly brace. "
Therefore, replace:
<xslt:template match="{$expression}">
<elem key="{name()}">
<xslt:copy-of select="@*"/>
<xslt:for-each select="@*">
<xslt:sort select="name()"/>
<attribute>|<xslt:value-of select="name()"/>|</attribute>
</xslt:for-each>
</elem>
</xslt:template>
with:
<xslt:template match="{$expression}">
<elem key="{{name()}}">
<xslt:copy-of select="@*"/>
<xslt:for-each select="@*">
<xslt:sort select="name()"/>
<attribute>|<xslt:value-of select="name()"/>|</attribute>
</xslt:for-each>
</elem>
</xslt:template>
and as result you will get:
<xsl:template match="//*[@name='Spot']">
<elem key="{name()}">
<xsl:copy-of select="@*" />
<xsl:for-each select="@*">
<xsl:sort select="name()" />
<attribute>|<xsl:value-of select="name()" />|</attribute>
</xsl:for-each>
</elem>
</xsl:template>
Note: I am surprised that this code works at all. You should be using the <xsl:namespace-alias>
XSLT instruction.
/
returns the node that contains the root node of the XML document, not the root node itself. This node does not have a name.
You want the name of the child of that node, I'm guessing. You can do it a number of ways. One is you can change your <xsl:template match="/">
to <xsl:template match="/root">
(where root
is whatever the root node's name is) or you can change <elem key="{name()}">
to <elem key="{name(root)}">
.
But you might not know the name in advance. If that's the case you can go with <xsl:template match="/*">
. That will return all children of the root's parent. In this case there is always only one root. Then you can use <elem key="{name()}">
normally.
精彩评论