Is there an XSLT name-of element?
Asked Answered
U

6

115

In XSLT there is the

<xsl:value-of select="expression"/>

to get the value of an element, but is there something to select the tag-name of the element?

In a situation like this:

<person>
  <!-- required stuff -->
  <name>Robert</name>
  <!-- optional stuff, free form for future extension. 
       Using XMLSchema's xsd:any -->
  <profession>programmer</profession>
  <hobby>photography</hobby>
</person>

<xsl:for-each select="person">
   <xsl:tag-of select="."/> : <xsl:value-of select="."/>
</xsl:for-each>

To get output like this:

name : Robert
profession : programmer
hobby : photography

Of course the above XSLT won't compile because

 <xsl:tag-of select="expression"/>

doesn't exist. But how could this be done?

Unreal answered 25/2, 2009 at 9:11 Comment(2)
The most relevant tag for this question is XPath. Both functions are XPath standard functions and can be used within an XPath expression in the context of any hosting language (C#, XSLT, XQuery, ...) Please, re-tagUnderlayer
This text: "In XSLT there is the <xsd:value-of select="expression"/>" -- contains an error. The usually used prefix for XSLT instructions is "xsl". Usually when using XML Schema we use the prefix "xsd" or "xs". Please, correct.Underlayer
S
175

This will give you the current element name (tag name)

<xsl:value-of select ="name(.)"/>

OP-Edit: This will also do the trick:

<xsl:value-of select ="local-name()"/>
Sp answered 25/2, 2009 at 9:19 Comment(2)
local-name is what you want 9 times out of 10Plastic
local-name is sans namespace, this is why it's usually better.Struve
U
112

Nobody did point the subtle difference in the semantics of the functions name() and local-name().

  • name(someNode) returns the full name of the node, and that includes the prefix and colon in case the node is an element or an attribute.
  • local-name(someNode) returns only the local name of the node, and that doesn't include the prefix and colon in case the node is an element or an attribute.

Therefore, in situations where a name may belong to two different namespaces, one must use the name() function in order for these names to be still distinguished.

And, BTW, it is possible to specify both functions without any argument:

name() is an abbreviation for name(.)

local-name() is an abbreviation for local-name(.)

Finally, do remember that not only elements and attributes have names, these two functions can also be used on PIs and on these they are identical).

Underlayer answered 25/2, 2009 at 14:53 Comment(0)
L
15
<xsl:for-each select="person">
  <xsl:for-each select="*">
    <xsl:value-of select="local-name()"/> : <xsl:value-of select="."/>
  </xsl:for-each>  
</xsl:for-each>
Luht answered 25/2, 2009 at 9:26 Comment(2)
As a good practice always use normalize-space() when getting value-of the node <xsl:value-of select="normalize-space(.)"/> This will trim the extra spacesSp
Such normalisation/sanitisation would only be needed if it hadn't been handled at the input gathering stage. Doing it then saves having to do it at access time, which is usually far more often. One would do it before adding to an RDB, and an xml document is just another database.Gentille
R
9

For those interested, there is no:

<xsl:tag-of select="."/>

However you can re-create the tag/element by going:

<xsl:element name="{local-name()}">
  <xsl:value-of select="substring(.,1,3)"/>
</xsl:element>

This is useful in an xslt template that for example handles formatting data values for lots of different elements. When you don't know the name of the element being worked on and you can still output the same element, and modify the value if need be.

Rugging answered 19/3, 2013 at 4:21 Comment(0)
K
6
<xsl:value-of select="name(.)" /> : <xsl:value-of select="."/>
Kidnap answered 25/2, 2009 at 9:20 Comment(5)
So why'd this get down voted? Granted could've mentioned local-name() if you didn't want the namespace as well, but it would be useful to the wider community to explain why this wouldn't work.Kidnap
Perhaps, it couldn't transform the given XML. the name(.) will be "person" in this case. it should be "name", "profession" and "hobby".Luht
@CodeMelt Why then you didn' downvote the accepted answer? It good, but is even less specific than this one. I up-voted Rowland Shaw's answer as it provides the answer to the question. Plese, downvote only when an aswer contains wrong, incorrect or misleading informationUnderlayer
Fixed that minor detail - personally, i think that people should explain why something is downvoted, as it helps explain the collective knowledge...Kidnap
Our reputations may attract attention, but as they are no guarantee that what we have posted is worthwhile, it is the quality of our contribution that really counts. No reasoning makes for poor quality contributions.Gentille
M
0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="person">
        <xsl:for-each select="*">
            <xsl:text>
       </xsl:text>
            <xsl:value-of select="local-name()"/> : <xsl:value-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
Marlette answered 28/7, 2021 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.