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 base.WriteProcessingInstruction("xml-stylesheet", String.Format("type=\"text/xsl\" href=\"{0}\"", stylesheet)); } base.WriteStartElement(prefix, localName, ns); } }And here is a usage sample:
DataSet ds = new DataSet(); ds.ReadXml("feedlist.xml"); ... XmlTextWriter w = new AddPIXmlTextWriter("foo.xml", Encoding.UTF8, "foo.xsl"); w.Formatting = Formatting.Indented; ds.WriteXml(w);And the resulting foo.xml starts with:
<?xml-stylesheet type="text/xsl" href="foo.xsl"?> <feeds refresh-rate="900000" xmlns="http://www.25hoursaday.com/2003/RSSBandit/feeds/"> <feed category="blogs"> ...