Friday, April 8, 2011

Is there an XSLT name-of element?

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?

From stackoverflow
  • 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()"/>
    
    Robert Gould : Thanks I just found it too. Also will work
    annakata : local-name is what you want 9 times out of 10
    Jweede : local-name is sans namespace, this is why it's usually better.
  •    <xsl:value-of select="name(.)" /> : <xsl:value-of select="."/>
    
    Rowland Shaw : 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.
    codemeit : Perhaps, it couldn't transform the given XML. the name(.) will be "person" in this case. it should be "name", "profession" and "hobby".
    Dimitre Novatchev : @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 information
    Rowland Shaw : Fixed that minor detail - personally, i think that people should explain why something is downvoted, as it helps explain the collective knowledge...
  •   <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>
    
    Rashmi Pandit : As a good practice always use normalize-space() when getting value-of the node This will trim the extra spaces
    codemeit : @Rashimi, thanks for point this out.
  • 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).

0 comments:

Post a Comment