Got more questions? Find advice on: ASP | SQL | Regular Expressions | Windows
in Search
Welcome to XmlAdvice Sign in | Join | Help

Kirk Allen Evans' XML Blog

.NET From a Markup Perspective

More d-o-e and XmlWriter

In my last post, I described the behavior of disable-output-escaping (d-o-e) and System.Xml.Xsl.XslTransform when serializing to an XmlTextWriter.  This is a vague concept if you haven't fought d-o-e before, so I am expanding the explanation a bit. 

 

XSLT is deceptive in that it looks like text (after all, you just type, and a processor parses it).  In fact, the same is said for XML.  The core concept to realize is that the IXPathNavigable instance passed to the Transform method does not contain text, but rather the object graph representation of the XML text.  Now that serialization has become much more common for developers, think of using a SOAPFormatter for de-serialization:  the XML strings are used to populate your objects.  This is the same concept for XSLT:  the strings that you read are de-serialized into an object graph, and that graph is then used for the transformation source.

 

The next concept is that of the XSLT result tree.  Even though XSLT is mainly used for “xml in, xml out“ transformations, it still accepts an object graph and forms a resulting object graph. The resulting object graph is referred to as the result tree.  That result tree may be serialized to strings, but the main purpose for the XSLT processor is to form the result tree. 

 

A secondary job of the XSLT processor is to serialize the result tree to text, but only under certain conditions.  One of those conditions is when the xsl:output method for the stylesheet is set to “text”:  this tells the processor to explicitly serialize the object graph to text.  The default output method for the stylesheet is “xml”, meaning that the result is not serialized and the object graph is instead maintained.

 

Now that we covered some basic XSLT review, let's look at some code.  Here is the stylesheet that I referenced yesterday:

 

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<root>

<xsl:text disable-output-escaping="yes"><![CDATA[<table/>]]></xsl:text>

<xsl:text disable-output-escaping="yes">&lt;table/></xsl:text>

<xsl:value-of disable-output-escaping="yes" select="'&lt;table/>'" />

</root>

</xsl:template>

</xsl:stylesheet>

 

The very first instruction within the stylesheet's single template creates an element named “root”.  Note that this is not text:  to create a text node, you would use the xsl:text element to create text.  This is specifically an element node named “root” that instructs the XSLT processor to add an element node in the result tree. 

 

Once the result tree is formed via XSLT processing, it is then serialized.  This is where the difference between the StringWriter and the XmlTextWriter occurs:  The StringWriter just writes out the string version of the serialized tree, whereas the XmlTextWriter actually works with the result tree directly.

 

Recall from above that d-o-e serializes the result to a text node, which is different than creating an element.  This is the biggest argument against using d-o-e, because the result is not an element:  it is, in fact, text that contains "<".  This is misleading if you aren't familiar with the concept of a result tree and the different node types that it can contain.  This is why most of the XSLT experts strongly advocate against using d-o-e except in a very few rare situations, such as generating an ASP.NET page directive.

 

When the StringWriter is used, the tree is serialized as-is.  The text node that contains "<table/><table/><table/>" is serialized directly to a string without any escaping.

 

The behavior is different when d-o-e is used; the XslTransform will call the WriteString method of the associated XmlWriter implementation, passing the literal value of:

 

<table/><table/><table/>

 

The XmlTextWriter is nice enough to recognize that you are passing text that contains illegal text characters according to XML 1.0, so it escapes the values for you:

 

&lt;table/&gt;&lt;table/&gt;&lt;table/&gt;

 

You can observe the behavior with the following console app.  Set breakpoints in the methods in the MyWriter class and you can observe the behavior.

 

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.XPath;

namespace MyWriter.ConformWriter
{
  class Class1
  {
    [STAThread]
    static void Main(string[] args)
    {
      System.Xml.Xsl.XslTransform trans = new System.Xml.Xsl.XslTransform();
      trans.Load(@"C:\temp\XSLTFile1.xslt",new XmlUrlResolver());
      XPathDocument doc = new XPathDocument(@"C:\temp\XMLFile1.xml");
      StringWriter sw= new StringWriter();
      MyWriter writer = new  MyWriter(sw);
      trans.Transform(doc,null,writer,new System.Xml.XmlUrlResolver());
      writer.Flush();
      System.Diagnostics.Debug.WriteLine(sw.ToString());    
    }
  }


  public class MyWriter : XmlTextWriter
  {
    public MyWriter(System.IO.TextWriter writer):base(writer){}

    public override void WriteString(String value)
    {      
      base.WriteString(value);
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
      base.WriteStartElement(prefix, localName, ns);
    }

    public override void WriteFullEndElement()
    {
      base.WriteFullEndElement();
    }
  }
}
 
Sponsor
Published Friday, January 30, 2004 11:35 AM by kaevans
Filed under: , ,

Comments

 

kaevans said:

October 25, 2004 7:37 PM
 

TrackBack said:

January 31, 2004 12:03 PM
Anonymous comments are disabled

This Blog

Syndication

News

Looking for a place to talk about XML? Tired of the "main feed police" cracking about your interests in football and politics? Sign up for a free web log on XMLAdvice.com.