Oct 31, 2008 at 5:58 pm, Stein
Tony Hirst was looking for a way to output all XML element names and PCDATA in a document and show hierarchical relationships. I guessed this was easy, so I tried but initially failed. I searched for an answer and was surprised when I couldn’t find a good one. An hour later I worked out a solution based on parent::node() that seems stable on all XML files. I post it here for future reference:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl=
"http://www.w3.org/1999/XSL/Transform">
<xsl:output type="xml" />
<xsl:template match="/">
<html>
<head>
<title>Untitled</title>
</head>
<body>
<xsl:for-each select="//*"><!--loop all levels of nodes-->
<xsl:if test="position() > 2"><br/></xsl:if><!--line break after last-->
<xsl:choose>
<xsl:when test="*"><!--does this node have children-->
<xsl:if test="position() > 1">
<!--print node + ancestor relationship-->
<xsl:value-of select="concat(name(parent::node()),'->',name())"/>
</xsl:if>
</xsl:when>
<xsl:when test=".=text()"><!--does this node have PCDATA-->
<!--print node + ancestor relationship-->
<xsl:value-of select="concat(name(parent::node()),'->',name())"/>
<br/>
<!--print node PCDATA-->
<xsl:value-of select="concat(name(),'->','"',text(),'"')"/>
</xsl:when>
</xsl:choose>
<xsl:if test="@* > 0"><!--does this node have attributes-->
(
<xsl:for-each select="@*"><!--for each name/value-->
<xsl:value-of select="name()"/>
=
<xsl:value-of select="."/>
</xsl:for-each>
)
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
