tags:

views:

34

answers:

2

Hi!

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! :)

A: 

/ 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.

Welbog
Sorry I don't believe this helps. I need to find the name of the element of the results returned from the XPath expression in <xslt:template match="{$expression}"> not the root element name of the XML doc used in the first XSL doc. (the XML doc used for the first XSL document is different than the XML doc used in the second XSL document, so there is very different data being used)
developer
+2  A: 

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.

Dimitre Novatchev
@Dimitre: Thanks! Escaping it with { works :) I am unsure what you mean in your last note though. I am using <xsl:namespace-alias stylesheet-prefix="xslt" result-prefix="xsl"/> at the top of the first XSL doc.
developer
@iHeartGreek: I see now. Because "xsl" and "xslt" look alike, I thought you were using only xsl... :)
Dimitre Novatchev
@Dimitre: haha yes they do! Thanks again for the simple and correct answer!
developer
@Dimitre: +1 Good answer and good question you did!
Alejandro