I have a string containing XML document using LinqtoXML
What is the best way of displaying it on an asp.net page as is.
I would have liked to do it the way Dennis has mentioned (using an <asp:Xml> control). But that necessitates the use of an XSL stylesheet to format the XML. The Xml control does not allow an HTML encoded string to be passed as the DocumentContent property and does not expose any method to encode the content.
As I have mentioned in the comments to Dennis' post, the defaultss.xsl contained within msxml.dll is not available publicly (and is not XSL 1.0 compliant). However, a public converted version was posted here: http://www.dpawson.co.uk/xsl/sect2/microsoft.html#d7615e227. I have tested it and it works, though a bit buggy.
Therefore, I think the simplest way would be to use an <asp:Literal> control to output pre-encoded XML to the page. The following sample demonstrates this method:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
string theXML = Server.HtmlEncode(File.ReadAllText(Server.MapPath("~/XML/myxmlfile.xml")));
lit1.Text = theXML;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<pre>
<asp:Literal ID="lit1" runat="server" />
</pre>
</div>
</form>
</body>
</html>
<asp:Literal ID="ReportXML" runat="server" Mode="Encode" />Use the asp:Xml control together with this Default Stylesheet as the TransformSource. This will give you a look very similar to what you see when you open an xml file in Internet Explorer complete with syntax highlighting and coloration.
I removed the expanding/collapsing node functionality because I couldn't get that to work. This file is xsl 1.0 and works great without bugs for my purposes.
To avoid any future problems with my linked file, here are the contents:
<!--
|
| 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">
<xsl:output indent="no" method="html"/>
<xsl:template match="/">
<xsl:apply-templates/>
</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><?</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><?</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><!--</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"><</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"><</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></</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><</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"></</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"><</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></</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">&</xsl:text>
<xsl:value-of select="$name"/>
<xsl:text>;</xsl:text>
</xsl:template>
</xsl:stylesheet>
Displaying XML Formatted Code Without Using an XML Control
Here is a VB.NET solution:
Public Shared Function FormatXml(ByVal xmlDoc As XmlDocument) As String
Dim sb As New StringBuilder()
`'We will use stringWriter to push the formated xml into our StringBuilder sb.`
Using stringWriter As New StringWriter(sb)
`'We will use the Formatting of our xmlTextWriter to provide our indentation.`
Using xmlTextWriter As New XmlTextWriter(stringWriter)
xmlTextWriter.Formatting = Formatting.Indented
xmlDoc.WriteTo(xmlTextWriter)
End Using
End Using
Return sb.ToString()
End Function
Use this Function to set the Text of a multiline TextBox or a Label:
XmlViewTextBox.Text = FormatXml(xmlDoc)
If you are trying to use an XML string, convert it to an XmlDocument first:
Dim xmlDoc As New XmlDocument
xmlDoc.LoadXml(xmlString)
This solution will render the XML code on the HTML page while preserving line-breaks and indents.
HTML PRE tags in a div, and just echo out the string properly escaped?
Div gives you alignment / formatting, while the PRE should preserve whitespace
For me to accomplish this, I needed to bring multiple sources together to make this work in ASP.Net Core MVC.
In Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// override XmlException: Resolving of external URIs was prohibited.
AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
In display.chtml:
<div>
@Html.Raw(ViewBag.TransformedXml)
</div>
Then in controller:
public string TransformCDA(string xml, HttpContext httpContext)
{
string TransformedXml = string.Empty;
XmlDocument XmlDoc = new XmlDocument();
string xsltPath = httpContext.MapPath("~/lib/xsl/CDA.xsl");
string xmlPath = httpContext.MapPath("~/lib/xsl/CDA.xml");
XmlDoc.LoadXml(xml);
var sb = new StringBuilder();
using (var stringWriter = new StringWriter(sb))
{
using (var xmlTextWriter = new XmlTextWriter(stringWriter))
{
// Create the XsltSettings object with document() enabled and script enabled.
XsltSettings settings = new XsltSettings(true, true);
// Create the XslCompiledTransform object and load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
var resolver = new XmlUrlResolver();
xslt.Load(xsltPath, settings, resolver);
xslt.Transform(XmlDoc, xmlTextWriter);
XmlDoc.WriteTo(xmlTextWriter);
}
}
ViewBag.TransformedXml = sb.ToString();
}
The "MapPath" genius is from Rick Strahl.
I hope this helps someone from having to bring all the pieces together.