In .NET 2.0 framework when using System.Xml.Xsl.XslCompiledTransform class for transforming a document then we always get self closing tags for all the elements which have nothing inside their body. There is no direct way to tell it to use separate closing tags e.g. <BODY> <TABLE></TABLE> <BR></BR> </BODY>
transforms as
<BODY> <TABLE/> <BR/> </BODY>
This might cause problems when we are transforming a document for HTML processing as HTML doesn't identify self closing tags properly. So although <Table/> is a valid XML closed tag but HTML identifies it as starting of a table only which causes its output to be different than what we want. This thing did not happen with System.Xml.Xsl.XslTransform class in .NET 1.1 framework. It gives separate closing tags for empty elements too
This problem is caused because xslcompiledtransform class uses self closing tags for all the elements irrespective of whether they are empty or not.
The resolution of the issue involves creating a class derived from XmlTextWriter and overriding few methods in it. Here are the steps:
using System; using System.Collections.Generic; using System.Text; using System.Xml; namespace XSLSelfClosing { public class XmlHtmlWriter : XmlTextWriter { public XmlHtmlWriter(System.IO.Stream stream, Encoding en) : base(stream, en) { //Put all the elemnts for which you want self closing tags in this list. //Rest of the tags would be explicitely closed fullyClosedElements.AddRange(new string[] { "br", "hr" }); } string openingElement = ""; List<string> fullyClosedElements = new List<string>(); public override void WriteEndElement() { if (fullyClosedElements.IndexOf(openingElement) < 0) WriteFullEndElement(); else base.WriteEndElement(); } public override void WriteStartElement(string prefix, string localName, string ns) { base.WriteStartElement(prefix, localName, ns); openingElement = localName; } } }
using System; using System.Collections.Generic; using System.Text; using System.Xml;
namespace XSLSelfClosing { public class XmlHtmlWriter : XmlTextWriter { public XmlHtmlWriter(System.IO.Stream stream, Encoding en) : base(stream, en) {
//Put all the elemnts for which you want self closing tags in this list. //Rest of the tags would be explicitely closed fullyClosedElements.AddRange(new string[] { "br", "hr" }); }
string openingElement = ""; List<string> fullyClosedElements = new List<string>();
public override void WriteEndElement() { if (fullyClosedElements.IndexOf(openingElement) < 0) WriteFullEndElement(); else base.WriteEndElement(); } public override void WriteStartElement(string prefix, string localName, string ns) { base.WriteStartElement(prefix, localName, ns); openingElement = localName; } } }