Render XML as HTML

Hi Folks,

I had to make a report on a website, where users could see data being sent into the Enterprise Service Bus. So basically all requests sent to web services is stored as XML in the SQL database.

So, I created a GridView with a link to display the XML data if needed. However IE will display it like text unless you use a Response.Write mechanism and modify the content-type to text/xml etc or load IE with xml file direcrlty. I find this a bit dirty, since you need to finalise with a Response.End(), and this can cause the browser to not allow navigatiing back on your pages. It is much better to have a button on page to view data, then the user clicks it, a popup box shows with the nicely html view of the xml, just like IE does it when opening an XML file!!

Also I can imagine a user getting annoyed, where evertime he views the XML data he needs to click the back button, so popups are cool here. You can also of course just put it into another page if you want etc.

So the solution is the following:

1. AJAX – modalpopupextender

2. System.Web.UI.WebControls.Xml

3. XSLT to tranform the XML to HTML – http://grounding.co.za/files/folders/documents/entry2193.aspx

Ok, what you do is put in a event handler on the gridview for the tenmplate column:

<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="linkButtonShowData" Text="Show" Font-Underline="true" Font-Bold="true"
ForeColor="Pink" CommandArgument="<%# Bind(‘aib_RequestData’) %>" runat="server"
OnClick="linkButtonShowData_Click" />
</ItemTemplate>
</asp:TemplateField>

Then the event handler will parse the xml data to a helper method which will call the modalpopupextender.

protected void linkButtonShowData_Click(object sender, EventArgs e)
{
LinkButton showDataButton = (LinkButton)sender;
bool isXml = false;
XmlDocument doc = new XmlDocument();
try
{
doc.LoadXml(showDataButton.CommandArgument);
isXml = true;
}
catch
{

}

if (isXml)
showXml(doc);
else
showText(showDataButton.CommandArgument);
}

protected void showText(string text)
{
if (text == string.Empty)
{
text = "No request data found.";
lblRequestData.Text = @"<H5>" + text + @"</H5>";
lblRequestData.ForeColor = System.Drawing.Color.Red;
}
else
{
lblRequestData.Text = text;
lblRequestData.ForeColor = System.Drawing.Color.Black;
}
CreateModalPopupExtender.Show();
}

protected void showXml(XmlDocument xml)
{
lblRequestData.Text = string.Empty;
XmlRequestData.DocumentContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + Environment.NewLine;
XmlRequestData.DocumentContent += xml.OuterXml;
XmlRequestData.TransformSource=@"~\XSLT\XMLToHtml.xslt";
CreateModalPopupExtender.Show();
}

From the above, we have to methods, if the XML is not valid, then we just show the text data as some wbe requests are not XML based.

Ok, so as you can see we load the xml into the XmlRequestData.DocumentContent. This is just a simple System.Web.UI.WebControls.Xml.

<asp:Xml ID="XmlRequestData" runat="server" />

Which is located in the popup control of ajax, see below:

<asp:Button ID="HiddenPopupButton" Style="display: none" runat="Server" />
<ajaxtoolkit:modalpopupextender id="CreateModalPopupExtender" targetcontrolid="HiddenPopupButton"
popupcontrolid="CreateModelPanel" cancelcontrolid="Close" backgroundcssclass="ModalBackground"
dropshadow="true" runat="server" />
<asp:Panel ID="CreateModelPanel" Style="display: none;" CssClass="ModalPopup" ScrollBars="Both"
runat="server">
<div class="PopUpContent">
<div>
<asp:Label ID="lblRequestData" runat="server" Width="100px" />
<asp:Xml ID="XmlRequestData" runat="server" />
</div>
<div>
<asp:Button ID="Close" Text="Close" runat="server" /><br />
<br />
<br />
</div>
</div>
</asp:Panel>

Now here is the magic!

XmlRequestData.DocumentContent += xml.OuterXml;
XmlRequestData.TransformSource=@"~\XSLT\XMLToHtml.xslt";
CreateModalPopupExtender.Show();

This will transform the xml control data into HTML using the xslt.

Below is the xslt:

——————————————————————-

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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:apply-templates/>
</BODY>
</HTML>
</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: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>

<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:text>&lt;?</xsl:text>
</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:text>&lt;!–</xsl:text>
</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">&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(.)"/>
<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">&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(.)"/>
<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: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">
<xsl:call-template name="entity-ref">
<xsl:with-param name="name">nbsp</xsl:with-param>
</xsl:call-template>
</SPAN>
<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(.)"/>
<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">&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>
<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(.)"/>
<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: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="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>

——————————————————————-

That is all there is to it, now you XML will be displayed as HTML, as rendered when opening a file in Internet Explorer with a nice format to it!

You can download the XSLT here:

http://grounding.co.za/files/folders/documents/entry2193.aspx

Advertisements
Uncategorized

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s