XSL to Output Elements, PCDATA, Attributes

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>

Comments are closed.