views:

572

answers:

3

When creating a doctype for an System.Xml.Linq.XDocument like this:

doc.AddFirst(new XDocumentType("html", null, null, null));

The resulting saved XML file starts with:

<!DOCTYPE html >

Notice the extra space before the closing angle bracket. How can I prevent this space appearing? I'd like a clean way if possible :)

A: 

I might be wrong but I think this space is because there are more parameters expected after the HTML. Although HTML5 allows it.

Try specifying at least the 3rd parameter as well (*.dtd). Or do something like this:

new XDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd", null)
DmitryK
This defeats the point of using the less crufty HTML5 doctype.
hsivonen
+1  A: 

You don't get the space if you write to an XmlTextWriter:

        XDocument doc = new XDocument();
        doc.AddFirst(new XDocumentType("html", null, null, null));
        doc.Add(new XElement("foo", "bar"));

        using (XmlTextWriter writer = new XmlTextWriter("c:\\temp\\no_space.xml", null)) {
            writer.Formatting = Formatting.Indented;
            doc.WriteTo(writer);
            writer.Flush();
            writer.Close();
        }
Luke Girvin
Interesting, however then I can't set the Settings property to leave out the XML declaration. I'm using XmlWriter.Create which lets me pass in the settings.
Andrew Davey
After some poking around in Reflector it seems that XmlTextWriter and XmlEncodedRawTextWriter have slightly different implementations of WriteDocType. This accounts for the extra space character.
Andrew Davey
+1  A: 

One approach is to write a wrapper class for the XmlWriter. So:

XmlWriter writer = new MyXmlWriterWrapper(XmlWriter.Create(..., settings))

Then for the MyXmlWriterWrapper class define each method on the XmlWriter class interface to pass the call straight through to the wrapped writer, except for the WriteDocType method. You can then define that as something like:

public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
    if ((pubid == null) && (sysid == null) && (subset == null))
    {
        this.wrappedWriter.WriteRaw("<!DOCTYPE HTML>");
    }
    else
    {
        this.wrappedWriter.WriteDocType(name, pubid, sysid, subset);
    }
}

Not an especially clean solution admittedly, but it'll do the job.

Alohci
I'm now doing something similar: writing the doctype manually with the underlying TextWriter, then using the XmlWriter to write the XDocument. I am not adding the XDocumentType object any more.
Andrew Davey