How to add a reference to XSLT stylesheet while writng DataSet data to XML

| 3 Comments | No TrackBacks

Say you've got a DataSet and you want to save its data as XML. DataSet.WriteXml() method does it perfectly well. But what if you need saved XML to have a reference to an XSLT stylesheet - xml-stylesheet processing instruction, such as <?xml-stylesheet type="text/xsl" href="foo.xsl"?> ? Of course you can load saved XML into XmlDocument, add the PI and then save it back, but don't you remember Jan Gray's Performance Pledge we took:

"I promise I will not ship slow code. Speed is a feature I care about. Every day I will pay attention to the performance of my code. I will regularly and methodically measure its speed and size. I will learn, build, or buy the tools I need to do this. It's my responsibility."
Come on, forget about XmlDocument. Think about perf and don't be lazy to look for a performance-oriented solution in the first place. Here is one simple streaming solution to the problem - small customized XmlWriter, which adds the PI on the fly during XML writing.

The idea is a trivial - DataSet.WriteXml() method accepts XmlWriter, so we can design a custom XmlWriter and encapsulate adding PI logic in it. xml-stylesheet PI must be placed in the document's prolog, so here is when to add it - once XmlWriter.WriteStartElement() method is called and the writer state is WriteState.Prolog or WriteState.Start (that means the first element's start tag is about to be written). Trivial and robust. Here is the implementation:

public sealed class AddPIXmlTextWriter : XmlTextWriter 
  private string stylesheet;

  //Constructors - add more as needed
  public AddPIXmlTextWriter(string filename, 
    Encoding enc, string stylesheet) 
  : base(filename, enc) 
    this.stylesheet = stylesheet;

  public override void WriteStartElement(string prefix, 
    string localName, string ns)
    if (WriteState == WriteState.Prolog || 
        WriteState == WriteState.Start) 
      //It's time to add the PI
        String.Format("type=\"text/xsl\" href=\"{0}\"", stylesheet));
    base.WriteStartElement(prefix, localName, ns);
And here is a usage sample:
    DataSet ds = new DataSet();
    XmlTextWriter w = new AddPIXmlTextWriter("foo.xml", Encoding.UTF8, "foo.xsl");
    w.Formatting = Formatting.Indented;        
And the resulting foo.xml starts with:
<?xml-stylesheet type="text/xsl" href="foo.xsl"?>
<feeds refresh-rate="900000" xmlns="">
  <feed category="blogs">

Related Blog Posts

No TrackBacks

TrackBack URL:


Nice work

Write *through* XmlTextWriter:

StringWriter sw = new StringWriter();
XmlTextWriter xw = new AddPIXmlTextWriter(sw);

You would need to add another constructor to the AddPIXmlTextWriter class, which accepts TextWriter then.


But I have a slightly different problem. Rather than writing to a file, I want to return the XML from a Web Service. If I write the XML from the dataset to a StringWriter, I have no such method to override. How would I then add the stylesheet to the XML?

Leave a comment