atownson
atownson

Reputation: 368

XML XSLT to display document tree

Is there an XSLT method to display an XML document in a web browser similar to Chrome, IE, and Firefox's document tree view (listing each element name and InnerText)? I am wanting a similar view functionality, but be able to apply certain styling to the InnerText values (primarily insert br tags). The XML template is fairly complex with many different parent and child elements, and it also includes comments but not attributes. Thank you.

So looking for:

<?xml version="1.0" encoding="utf-8">
<root>
  <!--
    Comment 1
    Comment 1 Continued
  -->
  <parent1>
    <child1>Child 1 InnerText</child1>
    <child2>
      Child 2 InnerText
      Child 2 InnerText Continued
    </child2>
  </parent>
</root>

To be displayed in a web browser like:

<root>
  <!--
    Comment 1
    Comment 1 Continued
  -->
  <parent1>
    <child1>Child 1 InnerText</child1>
    <child2>
      Child 2 InnerText
      Child 2 InnerText Continued
    </child2>
  </parent>
</root>

Instead of the web browser's default parser, which looks something like this (depending on the browser - IE below):

<?xml version="1.0" encoding="utf-8">
- <root>
    <!-- Comment 1Comment 1 Continued -->
  -  <parent1>
      <child1>Child 1 InnerText</child1>
      <child2>Child 2 InnerTextChild 2 InnerText Continued</child2>
  </parent>
</root>

Upvotes: 0

Views: 918

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167696

It is possible, yes, you can write a stylesheet that creates a HTML nested list or HTML nested table to render the markup. Here is a very simple example using a nested list:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="html" version="5.0" encoding="UTF-8" indent="yes" doctype-system="about:legacy-compat"/>

  <xsl:template match="/">
    <html>
      <head>
        <style type="text/css">
        ul { list-style-type: none; }
        .element { color: darkred; }
        .comment { color: lightgrey; }
        pre { margin: 0; }
        </style>
      </head>
      <body>
        <ul>
          <xsl:apply-templates/>
        </ul>
      </body>
     </html>
   </xsl:template>

   <xsl:template match="*">
     <li>
       <span class="element">
         <xsl:value-of select="concat('&lt;', name(), '&gt;')"/>
       </span>
       <xsl:if test="node()">
         <ul>
           <xsl:apply-templates/>
         </ul>
       </xsl:if>
       <span class="element">
         <xsl:value-of select="concat('&lt;/', name(), '&gt;')"/>
       </span>
     </li>
   </xsl:template>

   <xsl:template match="comment()">
     <li>
       <pre class="comment"><![CDATA[<!--]]><xsl:value-of select="."/><![CDATA[-->]]></pre>
     </li>
   </xsl:template>

   <xsl:template match="text()">
     <li>
       <pre>
         <xsl:value-of select="."/>
       </pre>
     </li>
   </xsl:template>

   <xsl:template match="text()[not(normalize-space())]"/>

</xsl:stylesheet>

When applied in Firefox to the corrected input sample

<root>
  <!--
    Comment 1
    Comment 1 Continued
  -->
  <parent1>
    <child1>Child 1 InnerText</child1>
    <child2>
      Child 2 InnerText
      Child 2 InnerText Continued
    </child2>
  </parent1>
</root>

the result is

<root>

    <!--
        Comment 1
        Comment 1 Continued
      -->

    <parent1>
        <child1>

            Child 1 InnerText

        </child1>
        <child2>


                  Child 2 InnerText
                  Child 2 InnerText Continued


        </child2>
    </parent1>
</root>

It is meant as a sample to show how to approach it, you might want to google for XSLT default stylesheet to find more sophisticated solutions.

Upvotes: 1

Related Questions