14

I have an existing XDocument object that I would like to add an XML doctype to. For example:

XDocument doc = XDocument.Parse("<a>test</a>");

I can create an XDocumentType using:

XDocumentType doctype = new XDocumentType("a", "-//TEST//", "test.dtd", "");

But how do I apply that to the existing XDocument?

James Sulak
  • 31,389
  • 11
  • 53
  • 57

2 Answers2

16

You can add an XDocumentType to an existing XDocument, but it must be the first element added. The documentation surrounding this is vague.

Thanks to Jeroen for pointing out the convenient approach of using AddFirst in the comments. This approach allows you to write the following code, which shows how to add the XDocumentType after the XDocument already has elements:

var doc = XDocument.Parse("<a>test</a>");
var doctype = new XDocumentType("a", "-//TEST//", "test.dtd", "");
doc.AddFirst(doctype);

Alternately, you could use the Add method to add an XDocumentType to an existing XDocument, but the caveat is that no other element should exist since it has to be first.

XDocument xDocument = new XDocument();
XDocumentType documentType = new XDocumentType("Books", null, "Books.dtd", null);
xDocument.Add(documentType);

On the other hand, the following is invalid and would result in an InvalidOperationException: "This operation would create an incorrectly structured document."

xDocument.Add(new XElement("Books"));
xDocument.Add(documentType);  // invalid, element added before doctype
Ahmad Mageed
  • 94,561
  • 19
  • 163
  • 174
  • Does this also apply for XDocument? The MSDN link points to XmlDocument. – dtb Sep 11 '09 at 20:49
  • 1
    @dtb: it does, but I couldn't find it stated on MSDN for XDocument. Also see the updated code and InvalidOperationException. – Ahmad Mageed Sep 11 '09 at 20:51
  • 1
    You can add an XDocumentType later, but you have to make sure that it is the first element in the `XDocument`. You can do that by using `xDocument.AddFirst(documentType)` instead off `xDocument.Add(documentType)`. – Jeroen Huinink May 31 '12 at 08:32
  • @Jeroen thanks, that's much more convenient. I've updated my response to include this information. – Ahmad Mageed May 31 '12 at 13:30
3

Just pass it to the XDocument constructor (full example):

XDocument doc = new XDocument(
    new XDocumentType("a", "-//TEST//", "test.dtd", ""),
    new XElement("a", "test")
);

or use XDocument.Add (the XDocumentType has to be added before the root element):

XDocument doc = new XDocument();
doc.Add(new XDocumentType("a", "-//TEST//", "test.dtd", ""));
doc.Add(XElement.Parse("<a>test</a>"));
dtb
  • 213,145
  • 36
  • 401
  • 431