Setting the XML Declaration With CMarkup

The XML Declaration is the version tag that appears at the beginning of document. It is optional when it is the default version 1.0 and ASCII (which is a subset of UTF-8) or any Unicode encoding.

<?xml version="1.0" encoding="UTF-8"?>

When you instantiate your CMarkup object, pass the XML declaration including a CRLF if you want.

CString strDecl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
CMarkup xml( strDecl + "\r\n" );

Or pass it to your SetDoc call.

xml.SetDoc( strDecl + "\r\n" );

If the document already exists and you want to add an XML declaration to the beginning, you can concatenate it to the document string and re-parse.

xml.SetDoc( strDecl + "\r\n" + xml.GetDoc() );

The most efficient way to add the XML declaration to the beginning of the existing document is with InsertNode and specifying only the data that goes inside the processing instruction (by the way, it adds the end of line automatically, see Node Methods in CMarkup).

CString strDeclData = "xml version=\"1.0\" encoding=\"UTF-8\"";
xml.InsertNode( xml.MNT_PROCESSING_INSTRUCTION, strDeclData );

You can actually specify it or modify it in pieces too.

if ( ! xml.FindNode(xml.MNT_PROCESSING_INSTRUCTION) )
    xml.InsertNode( xml.MNT_PROCESSING_INSTRUCTION, "xml" );
xml.SetAttrib( "version", "1.0" );
xml.SetAttrib( "encoding", "UTF-8" );

GetDeclaredEncoding is an efficient function to obtain the encoding from the declaration in an XML string without parsing the XML.

CMarkup Developer License

The MARKUP_VERSIONTAG define is supported in CMarkup Developer to automatically insert a simple <?xml version="1.0"?> declarion in new documents.


comment posted After Use SetDoc, Always "no root element"

David Odi 21-Jul-2005

Created new XML

m_Mark.SetDoc(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"));

then.. always the value of CMarkup::m_strError is "no root element"

Yes, when you initialize the document to just the XML declaration, it sets the error string to reflect the fact that there is no element. No cause for alarm. The error string in CMarkup lingers after an error condition until the next parse, even when a subsequent call resolves the error condition. GetError is most useful immediately after the CMarkup object is instantiated or SetDoc or Load.


comment posted declarations in write file mode

Mark Richards 25-May-2009

I've got large file writing mode working now, with one exception. My code uses the SetDoc method to add XML and style sheet declarations, like this:

CString sXMLHeader(_T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"));
if (m_bUseXSLT)
  sXMLHeader.Append(_T("<?xml-stylesheet type=\"text/xsl\" href=\"fs.xsl\"?>\r\n"));

I've noticed that when using MDF_WRITEFILE mode, SetDoc is not supported, so this code no longer works. Adding the XML declaration to the markup object constructor doesn't seem to work either. What's the right way to inject these declarations when using large file writing mode?

Great question. File write mode works differently because it is initiated with the Open method which clears the document buffer. Use AddNode after Open as follows:

CString strDecl = "xml version=\"1.0\" encoding=\"UTF-8\"";
CString strXsl = "xml-stylesheet type=\"text/xsl\" href=\"fs.xsl\"";
m_markup.Open( "filename", CMarkup::MDF_WRITEFILE );
m_markup.AddNode( CMarkup::MNT_PROCESSING_INSTRUCTION, strDecl );
if (m_bUseXSLT)
  m_markup. AddNode( CMarkup::MNT_PROCESSING_INSTRUCTION, strXsl );

You can also use SetAttrib with processing instructions if you feel the code is cleaner:

m_markup.AddNode( MNT_PROCESSING_INSTRUCTION, "xml-stylesheet" );
SetAttrib( "type", "text/xsl" );
SetAttrib( "href", "fs.xsl" );