Click here to Skip to main content
15,887,320 members
Articles / Desktop Programming / Windows Forms

XML String Browser (just like Internet Explorer) using the WebBrowser Control

Rate me:
Please Sign up or sign in to vote.
4.48/5 (15 votes)
14 Apr 2008CPOL6 min read 124.6K   3.2K   40  
This article will show you how to view a colourful collapsible treeview for XML Strings/XmlDocument in a browser (just like Internet Explorer) without the need for XML files.
��<?xml version="1.0" encoding="utf-16"?>

<!--

 |

 | XSLT REC Compliant Version of IE5 Default Stylesheet

 |

 | Original version by Jonathan Marsh (jmarsh@xxxxxxxxxxxxx)

 | http://msdn.microsoft.com/xml/samples/defaultss/defaultss.xsl

 |

 | Conversion to XSLT 1.0 REC Syntax by Steve Muench (smuench@xxxxxxxxxx)

 | 

 | Further conversion by George Zabanah as follows:

 |

 | 04-Apr-2008 George Zabanah Converted to XSLT 2.0 Stylesheet for use with Saxon

 |                            Added XML declaration

 |                            TODO: Need to add cdata, namespace handling, rendering improvements

 | 24-Mar-2008 George Zabanah Fix to cdata function. 

 |                            Was supposed to check cdata != null.

 |                            Instead my check was xpath != null

 |                            Changed for consistency.

 | 14-Mar-2008 George Zabanah Modifications made to the XSLT stylesheet

 |                            to add a little spacing and change default colour

 |                            of namespace

 |                            Fixed xml Namespace rendering

 |                            Added CDATA handling using exslt regExp

 |                            Added XML Processing Instruction (if available)

 |                            Added handling for xmlns:*

 +-->

<xsl:stylesheet version="2.0" 

                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" extension-element-prefixes="saxon">

  <xsl:param name="xmlinput"/>

  <xsl:strip-space elements="*"/>

  <xsl:output indent="no" method="html" />



  <xsl:template match="/">

    <HTML>

      <HEAD>

        <SCRIPT>

          <xsl:comment>

            <![CDATA[

                  function f(e){

                     if (e.className=="ci") {

                       if (e.children(0).innerText.indexOf("\n")>0) fix(e,"cb");

                     }

                     if (e.className=="di") {

                       if (e.children(0).innerText.indexOf("\n")>0) fix(e,"db");

                     } e.id="";

                  }

                  function fix(e,cl){

                    e.className=cl;

                    e.style.display="block";

                    j=e.parentElement.children(0);

                    j.className="c";

                    k=j.children(0);

                    k.style.visibility="visible";

                    k.href="#";

                  }

                  function ch(e) {

                    mark=e.children(0).children(0);

                    if (mark.innerText=="+") {

                      mark.innerText="-";

                      for (var i=1;i<e.children.length;i++) {

                        e.children(i).style.display="block";

                      }

                    }

                    else if (mark.innerText=="-") {

                      mark.innerText="+";

                      for (var i=1;i<e.children.length;i++) {

                        e.children(i).style.display="none";

                      }

                    }

                  }

                  function ch2(e) {

                    mark=e.children(0).children(0);

                    contents=e.children(1);

                    if (mark.innerText=="+") {

                      mark.innerText="-";

                      if (contents.className=="db"||contents.className=="cb") {

                        contents.style.display="block";

                      }

                      else {

                        contents.style.display="inline";

                      }

                    }

                    else if (mark.innerText=="-") {

                      mark.innerText="+";

                      contents.style.display="none";

                    }

                  }

                  function cl() {

                    e=window.event.srcElement;

                    if (e.className!="c") {

                      e=e.parentElement;

                      if (e.className!="c") {

                        return;

                      }

                    }

                    e=e.parentElement;

                    if (e.className=="e") {

                      ch(e);

                    }

                    if (e.className=="k") {

                      ch2(e);

                    }

                  }

                  function ex(){}

                  function h(){window.status=" ";}

                  document.onclick=cl;

              ]]>

          </xsl:comment>

        </SCRIPT>

        <STYLE>

          BODY {font:x-small 'Verdana'; margin-right:1.5em}

          .c  {cursor:hand}

          .b  {color:red; font-family:'Courier New'; font-weight:bold;

          text-decoration:none}

          .e  {margin-left:1em; text-indent:-1em; margin-right:1em}

          .k  {margin-left:1em; text-indent:-1em; margin-right:1em}

          .t  {color:#990000}

          .xt {color:#990099}

          .ns {color:red}

          .dt {color:green}

          .m  {color:blue}

          .tx {font-weight:bold}

          .db {text-indent:0px; margin-left:1em; margin-top:0px;

          margin-bottom:0px;padding-left:.3em;

          border-left:1px solid #CCCCCC; font:small Courier}

          .di {font:small Courier}

          .d  {color:blue}

          .pi {color:blue}

          .cb {text-indent:0px; margin-left:1em; margin-top:0px;

          margin-bottom:0px;padding-left:.3em; font:small Courier;

          color:#888888}

          .ci {font:small Courier; color:#888888}

          PRE {margin:0px; display:inline}

        </STYLE>

      </HEAD>

      <BODY class="st">

        <xsl:call-template name="xmlprocessinginstruction"/>

        <xsl:apply-templates/>

      </BODY>

    </HTML>

  </xsl:template>



  <xsl:template match="processing-instruction()">

    <DIV class="e">

      <SPAN class="b">

        &#160;

      </SPAN>

      <SPAN class="m">

        <xsl:text>&lt;?</xsl:text>

      </SPAN>

      <SPAN class="pi">

        <xsl:value-of select="name(.)"/>

        <xsl:value-of select="."/>

      </SPAN>

      <SPAN class="m">

        <xsl:text>?></xsl:text>

      </SPAN>

    </DIV>

  </xsl:template>



  <!-- added handling for xml namespace - GZ -->

  <xsl:template match="@*[starts-with(name(),'xml:')]">

    <xsl:text> </xsl:text>

    <SPAN class="ns">

      <xsl:value-of select="name()" />

    </SPAN>

    <SPAN class="m">="</SPAN>

    <B class="ns">

      <xsl:value-of select="."/>

    </B>

    <SPAN class="m">"</SPAN>

  </xsl:template>



  <xsl:template match="@*">

    <xsl:text> </xsl:text>

    <SPAN>

      <xsl:attribute name="class">

        <xsl:if test="xsl:*/@*">

          <xsl:text>x</xsl:text>

        </xsl:if>

        <xsl:text>t</xsl:text>

      </xsl:attribute>

      <xsl:value-of select="name(.)"/>

    </SPAN>

    <SPAN class="m">="</SPAN>

    <B>

      <xsl:value-of select="."/>

    </B>

    <SPAN class="m">"</SPAN>

  </xsl:template>



  <xsl:template match="text()">

    <DIV class="e">

      <SPAN class="b"> </SPAN>

      <SPAN class="tx">

        <xsl:value-of select="."/>

      </SPAN>

    </DIV>

  </xsl:template>



  <xsl:template match="comment()">

    <DIV class="k">

      <SPAN>

        <A STYLE="visibility:hidden" class="b" onclick="return false" 

           onfocus="h()">-</A>

        <xsl:text> </xsl:text>

        <SPAN class="m">

          <xsl:text>&lt;!--</xsl:text>

        </SPAN>

      </SPAN>

      <SPAN class="ci" id="clean">

        <PRE>

          <xsl:value-of select="."/>

        </PRE>

      </SPAN>

      <SPAN class="b">

        &#160;

      </SPAN>

      <SPAN class="m">

        <xsl:text>--></xsl:text>

      </SPAN>

      <SCRIPT>f(clean);</SCRIPT>

    </DIV>

  </xsl:template>



  <xsl:template match="*">

    <DIV class="e">

      <DIV STYLE="margin-left:1em;text-indent:-2em">

        <SPAN class="b">

          &#160;

        </SPAN>

        <SPAN class="m">&lt;</SPAN>

        <SPAN>

          <xsl:attribute name="class">

            <xsl:if test="xsl:*">

              <xsl:text>x</xsl:text>

            </xsl:if>

            <xsl:text>t</xsl:text>

          </xsl:attribute>

          <xsl:value-of select="name(.)"/>

        </SPAN>

        <xsl:apply-templates select="@*"/>

        <SPAN class="m">

          <xsl:text>/></xsl:text>

        </SPAN>

      </DIV>

    </DIV>

  </xsl:template>



  <xsl:template match="*[node()]">

    <DIV class="e">

      <DIV class="c">

        <A class="b" href="#" onclick="return false" onfocus="h()">-</A>

        <xsl:text> </xsl:text>

        <SPAN class="m">&lt;</SPAN>

        <SPAN>

          <xsl:attribute name="class">

            <xsl:if test="xsl:*">

              <xsl:text>x</xsl:text>

            </xsl:if>

            <xsl:text>t</xsl:text>

          </xsl:attribute>

          <xsl:value-of select="name(.)"/>

        </SPAN>

        <xsl:apply-templates select="@*"/>

        <SPAN class="m">

          <xsl:text>></xsl:text>

        </SPAN>

      </DIV>

      <DIV>

        <xsl:apply-templates/>

        <DIV>

          <SPAN class="b">

            &#160;

          </SPAN>

          <xsl:text> </xsl:text>

          <SPAN class="m">

            <xsl:text>&lt;/</xsl:text>

          </SPAN>

          <SPAN>

            <xsl:attribute name="class">

              <xsl:if test="xsl:*">

                <xsl:text>x</xsl:text>

              </xsl:if>

              <xsl:text>t</xsl:text>

            </xsl:attribute>

            <xsl:value-of select="name(.)"/>

          </SPAN>

          <SPAN class="m">

            <xsl:text>></xsl:text>

          </SPAN>

        </DIV>

      </DIV>

    </DIV>

  </xsl:template>



  <xsl:template match="*[text() and not (comment() or processing-instruction())]">

    <DIV class="e">

      <DIV STYLE="margin-left:1em;text-indent:-2em">

        <SPAN class="b">

          &#160;

        </SPAN>

        <xsl:text> </xsl:text>

        <SPAN class="m">

          <xsl:text>&lt;</xsl:text>

        </SPAN>

        <SPAN>

          <xsl:attribute name="class">

            <xsl:if test="xsl:*">

              <xsl:text>x</xsl:text>

            </xsl:if>

            <xsl:text>t</xsl:text>

          </xsl:attribute>

          <xsl:value-of select="name(.)"/>

        </SPAN>

        <xsl:apply-templates select="@*"/>

        <SPAN class="m">

          <xsl:text>></xsl:text>

        </SPAN>

        <SPAN class="tx">

          <xsl:value-of select="."/>

        </SPAN>

        <SPAN class="m">&lt;/</SPAN>

        <SPAN>

          <xsl:attribute name="class">

            <xsl:if test="xsl:*">

              <xsl:text>x</xsl:text>

            </xsl:if>

            <xsl:text>t</xsl:text>

          </xsl:attribute>

          <xsl:value-of select="name(.)"/>

        </SPAN>

        <SPAN class="m">

          <xsl:text>></xsl:text>

        </SPAN>

      </DIV>

    </DIV>

  </xsl:template>



  <xsl:template match="*[*]" priority="20">

    <DIV class="e">

      <DIV STYLE="margin-left:1em;text-indent:-2em" class="c">

        <A class="b" href="#" onclick="return false" onfocus="h()">-</A>

        <xsl:text> </xsl:text>

        <SPAN class="m">&lt;</SPAN>

        <SPAN>

          <xsl:attribute name="class">

            <xsl:if test="xsl:*">

              <xsl:text>x</xsl:text>

            </xsl:if>

            <xsl:text>t</xsl:text>

          </xsl:attribute>

          <xsl:value-of select="name(.)"/>

        </SPAN>

        <xsl:apply-templates select="@*"/>

        <SPAN class="m">

          <xsl:text>></xsl:text>

        </SPAN>

      </DIV>

      <DIV>

        <xsl:apply-templates/>

        <DIV>

          <SPAN class="b">

            &#160;

          </SPAN>

          <xsl:text> </xsl:text>

          <SPAN class="m">

            <xsl:text>&lt;/</xsl:text>

          </SPAN>

          <SPAN>

            <xsl:attribute name="class">

              <xsl:if test="xsl:*">

                <xsl:text>x</xsl:text>

              </xsl:if>

              <xsl:text>t</xsl:text>

            </xsl:attribute>

            <xsl:value-of select="name(.)"/>

          </SPAN>

          <SPAN class="m">

            <xsl:text>></xsl:text>

          </SPAN>

        </DIV>

      </DIV>

    </DIV>

  </xsl:template>



  <xsl:template name="xmlprocessinginstruction">

    <xsl:if test="matches($xmlinput,'^(&lt;\?[ ]*xml[^>]*&gt;)')">

      <xsl:variable name="xmldec" select="substring($xmlinput,1, string-length($xmlinput) - string-length(replace($xmlinput,'^(&lt;\?[ ]*xml[^>]*&gt;)','')))"/>

        <DIV class="e">

          <SPAN class="b">

            &#160;

          </SPAN>

          <xsl:text> </xsl:text>

          <SPAN class="pi">

            <xsl:value-of select="replace(replace($xmldec,'&lt;\?[ ]*','&lt;? '),'[ ]*\?>',' ?>')"/>            

          </SPAN>

        </DIV>

    </xsl:if>

  </xsl:template>

</xsl:stylesheet>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Australia Australia
George Zabanah has been architecting and developing solutions commercially from start to finish for over 11 years. He has been programming since he was 11 (for over 25 years now!) using many different technologies (almost all Microsoft). George is proficient in many languages and employs best practices wherever possible using design patterns, .NET, XSLT, XML, Regular Expressions, various flavours of SQL (to name just a few). His favourite tools, however, are the whiteboard and Sparx Enterprise Architect/Powerpoint. Many waking moments have been spent by George thinking about solutions in his head (even while watching tv). His best moments are the "Eureka" moments when he wakes up from a good sleep (or after watching tv) to find that his latest challenge has been solved!

Comments and Discussions