0

This code is supposed to print the full path to all elements and attributes in the data.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">

   <xsl:output method="text"/>
   <xsl:template match="text()"/>

   <xsl:template match="*">
       {ancestor-or-self::*/concat(node-name(),'/')}<xsl:apply-templates select="@*|*"/>
   </xsl:template>
   <xsl:template match="@*">{'@' || node-name() || ','}</xsl:template>

 </xsl:stylesheet>

So with this input

<a:b xmlns:a="ans" xmlns:c="cns">
    <c:x/>
</a:b>

I expect

{ans}b
{ans}b/ {cns}x

precise spacing is immaterial.

I am getting output as if I had used the name() function instead of node-name i.e

a:b
a:b / c:x

There is probably a work-around by concatenating local-name and namespace-uri but I would like to know why what is posted isn't doing what I hoped it would.

Ihe Onwuka
  • 467
  • 1
  • 3
  • 11

1 Answers1

3

Perhaps the path function helps: <xsl:value-of select="descendant::*!path()" separator="&#10;"/>.

Or construct the format you want from namespace-uri-from-QName and the local-name-fromQName:

<xsl:value-of select="descendant::*!string-join(ancestor-or-self::*!node-name()!('{' || namespace-uri-from-QName(.) || '}' || local-name-from-QName(.)), '/')" separator="&#10;"/>

https://xsltfiddle.liberty-development.net/naZXVFj

As for why node-name() returns an xs:QName but its string value gives the format you see, I think https://www.w3.org/TR/xpath-functions-31/#casting-to-string specifies about casting an xs:QName to a string:

If ST is xs:QName or xs:NOTATION:

if the qualified name has a prefix, then TV is the concatenation of the prefix of SV, a single colon (:), and the local name of SV.

otherwise TV is the local-name.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110