How can I display XML with WebBrowser control?

39,383

Solution 1

Not particularly easy but possible. Either you save your string in a xml file and load it back using Navigate() (yuck...), or you apply a xsl to your xml (no kidding!) that renders it like the IE browser does.

see:

http://social.msdn.microsoft.com/Forums/en/winforms/thread/18ca6734-ddb7-4f44-a77c-9a7713dcc2e1

Solution 2

To give some code to the first solution @PaoloFalabella suggested (i.e. write string contents to a temporary xml file and navigate to it):

//create a random temporary file with an .xml file extension
var path = Path.GetTempPath();
var fileName = Guid.NewGuid().ToString() + ".xml";
var fullFileName = Path.Combine(path, fileName);
//write the contents of your xml string to the temporary file we just created
File.WriteAllText(fullFileName, xmlText); //xmlText is your xml string
//"navigate" to the file
webBrowser.Navigate(fullFileName); //webBrowser is your WebBrowser control

Solution 3

Here, I am providing a step-by-step solution to display XML file inside WebBrowser control.

  1. Add a WebBrowser control in a WinForm.
  2. Locate the defaultss.xsl somewhere inside your source folder.
  3. And copy below method.

    private void DisplayXml()
    {
        string xmlString = "<Person><Name>Fawad</Name><Age>23</Age></Person>";
    
        // Load the xslt used by IE to render the xml
        XslCompiledTransform xTrans = new XslCompiledTransform();
        xTrans.Load(Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.FullName, @"resources\defaultss.xsl"));
    
        // Read the xml string.
        StringReader sr = new StringReader(xmlString);
        XmlReader xReader = XmlReader.Create(sr);
    
        // Transform the XML data
        MemoryStream ms = new MemoryStream();
        xTrans.Transform(xReader, null, ms);
    
        ms.Position = 0;
    
        // Set to the document stream
        webBrowser1.DocumentStream = ms;
    }
    

I am copying the content of "defaultss.xsl" here for those who couldn't find it anywhere. Just simply past it in a notepad file and save it as xsl format inside folder "resources" or name it anything you wish.

<!--
 |
 | 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)
 |
 +-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- Add doctype attributes to keep IE happy -->
  <xsl:output indent="no"
                method="html"
                doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
                doctype-system="http://www.w3.org/tr/xhtml1/DTD/xhtml1-transitional.dtd" />
  <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:small 'Verdana'; margin-right:1.5em; margin-top: 44px;}
          .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:x-small Courier}
          .di {font:x-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:x-small Courier;
          color:#888888}
          .ci {font:x-small Courier; color:#888888}
          PRE {margin:0px; display:inline}

          .label {padding-left:20px; vertical-align: middle}
          .validation {color: white; padding: 3px; margin: 5px 5px 5px 5px; text-indent: 0}
          .summary {position: fixed; top: 0; left: 0; margin: 0px; padding-top: 10px; width: 100%; height: 32px; font-size: 12pt; vertical-align: middle;border-bottom: 2px solid black}
          .nav {float: right; padding-right:20px;}
          .failure {background: red;}
          .success {background: green;}
          .warning {background: yellow; color: black}
          .selected {font-weight: bold; text-indent: 1em}
        </STYLE>
      </HEAD>
      <BODY class="st">
        <xsl:apply-templates/>
      </BODY>
    </HTML>
  </xsl:template>

  <!-- Render the schema summary
         Include jquery from CDN and render a title bar across top -->
  <xsl:template match="processing-instruction('schemaSummary')">
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <div id="schemaSummary" class="validation summary">
      <span class="label">
        <xsl:value-of select="." />
      </span>
      <span class="nav">
        <button id="prev">&lt;&lt;</button>
        <button id="next">>></button>
      </span>
    </div>
  </xsl:template>

  <!-- Handle the schemaValid processing instruction 
         This sets up a document.ready routine that 
         colour codes a visual queue i.e. a green title bar.
    -->
  <xsl:template match="processing-instruction('schemaValid')">
    <script>
      $(document).ready(function() {
      $("#schemaSummary").addClass("success")
      $("button").css("display", "none");
      });
    </script>
  </xsl:template>

  <!-- Handle the schemaInvalid processing instruction
         Renders a red title bar with navigation controls to
         step through the errors.    
     -->
  <xsl:template match="processing-instruction('schemaInvalid')">
    <script>
      <![CDATA[
            var index = -1;
            var errors = $("div.failure");
            var offsetFromTop = $("#schemaSummary").outerHeight();
            function nextError(){
                if(index > -1) 
                    $(errors).eq(index).removeClass("selected");
                index ++;
                if(index >= $(errors).size())
                    index = 0;

                $(errors).eq(index).addClass("selected");                                       
                scrollTo($(errors).eq(index), offsetFromTop);
            }
            function prevError(){
                $(errors).eq(index).removeClass("selected");
                index --;
                if(index < 0)
                    index = $(errors).size() - 1;

                $(errors).eq(index).addClass("selected");                                       
                scrollTo($(errors).eq(index), offsetFromTop);               
            }
            function scrollTo(element, offsetFromTop) {
                $('html,body').animate({scrollTop: $(element).offset().top - offsetFromTop},'fast');
            }

            $(document).ready(function() {
                $("#schemaSummary").addClass("warning");
                $("#next").click(function() {
                    nextError();
                });
                $("#prev").click(function() {
                    prevError();
                });
            });
            ]]>
    </script>
  </xsl:template>

  <!-- Add a colour coded bar in situ i.e. where the validation
         error has occured -->
  <xsl:template match="processing-instruction('error')">
    <div class="validation failure">
      <xsl:value-of select="."></xsl:value-of>
    </div>
  </xsl:template>

  <xsl:template match="processing-instruction()">
    <DIV class="e">
      <SPAN class="b">
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">nbsp</xsl:with-param>
        </xsl:call-template>
      </SPAN>
      <SPAN class="m">
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">lt</xsl:with-param>
        </xsl:call-template>?
      </SPAN>
      <SPAN class="pi">
        <xsl:value-of select="name(.)"/>
      </SPAN>
      <SPAN>
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">nbsp</xsl:with-param>
        </xsl:call-template>
        <xsl:value-of select="."/>
      </SPAN>
      <SPAN class="m">
        <xsl:text>?></xsl:text>
      </SPAN>
    </DIV>
  </xsl:template>
  <xsl:template match="processing-instruction('xml')">
    <DIV class="e">
      <SPAN class="b">
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">nbsp</xsl:with-param>
        </xsl:call-template>
      </SPAN>
      <SPAN class="m">
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">lt</xsl:with-param>
        </xsl:call-template>?
      </SPAN>
      <SPAN class="pi">
        <xsl:text>xml </xsl:text>
        <xsl:for-each select="@*">
          <xsl:value-of select="name(.)"/>
          <xsl:text>="</xsl:text>
          <xsl:value-of select="."/>
          <xsl:text>" </xsl:text>
        </xsl:for-each>
      </SPAN>
      <SPAN class="m">
        <xsl:text>?></xsl:text>
      </SPAN>
    </DIV>
  </xsl:template>
  <xsl:template match="@*">
    <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>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>!--
        </SPAN>
      </SPAN>
      <SPAN class="ci" id="clean">
        <PRE>
          <xsl:value-of select="."/>
        </PRE>
      </SPAN>
      <SPAN class="b">
        <xsl:call-template name="entity-ref">
          <xsl:with-param name="name">nbsp</xsl:with-param>
        </xsl:call-template>
      </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">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">nbsp</xsl:with-param>
          </xsl:call-template>
        </SPAN>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>
        </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(.)"/>
          <xsl:if test="@*">
            <xsl:text> </xsl:text>
          </xsl:if>
        </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>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>
        </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(.)"/>
          <xsl:if test="@*">
            <xsl:text> </xsl:text>
          </xsl:if>
        </SPAN>
        <xsl:apply-templates select="@*"/>
        <SPAN class="m">
          <xsl:text>></xsl:text>
        </SPAN>
      </DIV>
      <DIV>
        <xsl:apply-templates/>
        <DIV>
          <SPAN class="b">
            <xsl:call-template name="entity-ref">
              <xsl:with-param name="name">nbsp</xsl:with-param>
            </xsl:call-template>
          </SPAN>
          <SPAN class="m">
            <xsl:call-template name="entity-ref">
              <xsl:with-param name="name">lt</xsl:with-param>
            </xsl:call-template>?/
          </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">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">nbsp</xsl:with-param>
          </xsl:call-template>
        </SPAN>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>
        </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(.)"/>
          <xsl:if test="@*">
            <xsl:text> </xsl:text>
          </xsl:if>
        </SPAN>
        <xsl:apply-templates select="@*"/>
        <SPAN class="m">
          <xsl:text>></xsl:text>
        </SPAN>
        <SPAN class="tx">
          <xsl:value-of select="."/>
        </SPAN>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>/
        </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>
        <SPAN class="m">
          <xsl:call-template name="entity-ref">
            <xsl:with-param name="name">lt</xsl:with-param>
          </xsl:call-template>
        </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(.)"/>
          <xsl:if test="@*">
            <xsl:text> </xsl:text>
          </xsl:if>
        </SPAN>
        <xsl:apply-templates select="@*"/>
        <SPAN class="m">
          <xsl:text>></xsl:text>
        </SPAN>
      </DIV>
      <DIV>
        <xsl:apply-templates/>
        <DIV>
          <SPAN class="b">
            <xsl:call-template name="entity-ref">
              <xsl:with-param name="name">nbsp</xsl:with-param>
            </xsl:call-template>
          </SPAN>
          <SPAN class="m">
            <xsl:call-template name="entity-ref">
              <xsl:with-param name="name">lt</xsl:with-param>
            </xsl:call-template>/
          </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="entity-ref">
    <xsl:param name="name"/>
    <xsl:text disable-output-escaping="yes">&amp;</xsl:text>
    <xsl:value-of select="$name"/>
    <xsl:text>;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

Solution 4

There is a good link here: Displaying XML in the .NET WebBrowser Control

public XmlDocument DocumentXml
{
  set
  {
    Stream s = <defaultss.xsl from embedded resource file>

    XmlReader xr = XmlReader.Create(s);
    XslCompiledTransform xct = new XslCompiledTransform();
    xct.Load(xr);

    StringBuilder sb = new StringBuilder();
    XmlWriter xw = XmlWriter.Create(sb);
    xct.Transform(value, xw);

    this.DocumentText = sb.ToString();
  }
}

Solution 5

The answer is very simple. We just have to use the DocumentText property of the WebBrowser control like this:

this.webBrowserControl.DocumentText = varWithXMLString;

A detail that I didn't find in the control's documentation is that the string must meet the following requirements:

  1. It must be a well-formed XML document
  2. The XML prolog must be included: <?xml version="1.0"?>
  3. It must be verified that the XML string doesn't include the UTF-8 BOM character (the reason why I did this research). This is something hard to detect through C# string convertions beeing that it generates a non-printable character, that is only visible when the string is casted to a byte or int array.

In the following Github repository is the example that I developed to show these validations: https://github.com/batressc/WinFormsWebBrowserXML

In the following link you can see in detail the development of the example (in Spanish): http://batrianoworld.batressc.com/2018/07/22/visualizacion-de-xml-utilizando-control-webbrowser-de-windowsforms

Share:
39,383
BrunoLM
Author by

BrunoLM

I'm a Developer for Fun! Things I like Code Play games Anime / Manga Contact information [email protected] LinkedIn Facebook Site - https://brunolm.github.io/ Blog - http://blog.codingwise.com/

Updated on July 21, 2022

Comments

  • BrunoLM
    BrunoLM almost 2 years

    I have a string that contains a xml. I want to set the value of the WebBrowser control with it and display as a xml.

    I can set the value with browser.DocumentText, but how do I tell it to display as a XML ?