This application creates a simple, but complete, XML DOM object, with <root> as the document element. This element contains three child elements: <node1>, <node2>, and <node3>. The first child element contains character data. The second child element contains a CDATA section. The last child element contains three empty child elements: <subnode1>, <subnode2>, and <subnode3>.
Programmatically, the dynamDOM application performs the following steps:
pXMLDom).createProcessInstruction method on pXMLDom. This creates a processing instruction node (pi) targeted for XML 1.0.appendChild method on pXMLDom. This adds the processing instruction node (pi) to pXMLDom.createComment method on the DOM object (pXMLDom) to create a comment node (pc) and then append it pXMLDom.<root> element as the document element, with a created attribute whose value is set to a string value of "using DOM". Adds this element (<root>) to the DOM object (pXMLDom).<node1> element with some character data as its content. Appends this element (pe) to the <root> element of the DOM object (pXMLDom).<node2> element that contains a CDATA section (pcd) with markup text. Appends this element (pe) to the <root> element of the DOM object (pXMLDom).<node3> element that contains a DOM document fragment (pdf). This fragment contains three other empty child elements: <subNode1>, <subNode2>, and <subNode3>. The code then appends this element (pe) to the <root> element of the DOM object (pXMLDom).C/C++ Source File (dynamDOM.cpp)
#include <stdio.h>
#include <windows.h>
#import <msxml5.dll> raw_interfaces_only
using namespace MSXML2;
// Macro that calls a COM method returning HRESULT value:
#define HRCALL(a, errmsg) \
do { \
hr = (a); \
if (FAILED(hr)) { \
dprintf( "%s:%d HRCALL Failed: %s\n 0x%.8x = %s\n", \
__FILE__, __LINE__, errmsg, hr, #a ); \
goto clean; \
} \
} while (0)
// Helper function that put output in stdout and debug window
// in Visual Studio:
void dprintf( char * format, ...)
{
static char buf[1024];
va_list args;
va_start( args, format );
vsprintf( buf, format, args );
va_end( args);
OutputDebugStringA( buf);
printf("%s", buf);
}
// Helper function to create a DOM instance.
IXMLDOMDocument * DomFromCOM()
{
HRESULT hr;
IXMLDOMDocument *pxmldoc = NULL;
HRCALL( CoCreateInstance(__uuidof(DOMDocument50),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXMLDOMDocument),
(void**)&pxmldoc),
"Create a new DOMDocument");
HRCALL( pxmldoc->put_async(VARIANT_FALSE),
"should never fail");
HRCALL( pxmldoc->put_validateOnParse(VARIANT_FALSE),
"should never fail");
HRCALL( pxmldoc->put_resolveExternals(VARIANT_FALSE),
"should never fail");
HRCALL( pxmldoc->put_preserveWhiteSpace(VARIANT_TRUE),
"should never fail");
return pxmldoc;
clean:
if (pxmldoc)
{
pxmldoc->Release();
}
return NULL;
}
VARIANT VariantString(BSTR str)
{
VARIANT var;
VariantInit(&var);
V_BSTR(&var) = SysAllocString(str);
V_VT(&var) = VT_BSTR;
return var;
}
// Helper function to display xml parse error:
void ReportParseError(IXMLDOMDocument *pDom, char *desc) {
IXMLDOMParseError *pXMLErr=NULL;
BSTR bstrReason = NULL;
HRESULT hr;
HRCALL(pDom->get_parseError(&pXMLErr),
"dom->get_parseError: ");
HRCALL(pXMLErr->get_reason(&bstrReason),
"parseError->get_reason: ");
dprintf("%s %S\n",desc, bstrReason);
clean:
if (pXMLErr) pXMLErr->Release();
if (bstrReason) SysFreeString(bstrReason);
}
// Helper function to append a whitespace text node to a
// specified element:
void AddWhiteSpaceToNode(IXMLDOMDocument* pDom,
BSTR bstrWs,
IXMLDOMNode *pNode)
{
HRESULT hr;
IXMLDOMText *pws=NULL;
IXMLDOMNode *pBuf=NULL;
HRCALL(pDom->createTextNode(bstrWs,&pws), " ");
HRCALL(pNode->appendChild(pws,&pBuf)," ");
clean:
if (pws) pws->Release();
pws=NULL;
if (pBuf) pBuf->Release();
pBuf=NULL;
}
// Helper function to append a child to a parent node:
void AppendChildToParent(IXMLDOMNode *pChild, IXMLDOMNode *pParent)
{
HRESULT hr;
IXMLDOMNode *pNode=NULL;
HRCALL(pParent->appendChild(pChild, &pNode), "");
clean:
if (pNode) pNode->Release();
pNode=NULL;
}
int main(int argc, char* argv[])
{
IXMLDOMDocument *pXMLDom=NULL;
IXMLDOMProcessingInstruction *pi=NULL;
IXMLDOMComment *pc=NULL;
IXMLDOMElement *pe=NULL;
IXMLDOMElement *pRoot=NULL;
IXMLDOMAttribute *pa=NULL;
IXMLDOMAttribute *pa1=NULL;
IXMLDOMCDATASection *pcd=NULL;
IXMLDOMElement *peSub=NULL;
IXMLDOMDocumentFragment *pdf=NULL;
BSTR bstr = NULL;
BSTR bstr1 = NULL;
BSTR bstr_wsn = SysAllocString(L"\n");
BSTR bstr_wsnt= SysAllocString(L"\n\t");
BSTR bstr_wsntt=SysAllocString(L"\n\t\t");
VARIANT var;
HRESULT hr;
CoInitialize(NULL);
VariantInit(&var);
pXMLDom = DomFromCOM();
if (!pXMLDom) goto clean;
// Create a processing instruction element.
bstr = SysAllocString(L"xml");
bstr1 = SysAllocString(L"version='1.0'");
HRCALL(pXMLDom->createProcessingInstruction(
bstr,bstr1, &pi),
"createProcessingInstruction:");
AppendChildToParent(pi, pXMLDom);
pi->Release();
pi=NULL;
SysFreeString(bstr);
bstr=NULL;
SysFreeString(bstr1);
bstr1=NULL;
// Create a comment element.
bstr = SysAllocString(L"sample xml file created using XML DOM object.");
HRCALL(pXMLDom->createComment(bstr, &pc), "");
AppendChildToParent(pc, pXMLDom);
SysFreeString(bstr);
bstr=NULL;
pc->Release();
pc=NULL;
// Create the root element.
bstr = SysAllocString(L"root");
HRCALL(pXMLDom->createElement(bstr, &pRoot), "");
SysFreeString(bstr);
bstr = NULL;
// Create a "created" attribute for the <root> element, and
// assign the "using dom" character data as the attribute value.
bstr = SysAllocString(L"created");
var = VariantString(L"using dom");
HRCALL(pXMLDom->createAttribute(bstr,&pa), "");
HRCALL(pa->put_value(var), "");
HRCALL(pRoot->setAttributeNode(pa, &pa1), "");
AppendChildToParent(pRoot, pXMLDom);
SysFreeString(bstr);
bstr=NULL;
if (pa1) {
pa1->Release();
pa1=NULL;
}
pa->Release();
pa=NULL;
VariantClear(&var);
// Next, we will create and add three nodes to the <root> element.
// Add NEWLINE+TAB for identation before <node1>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsnt, pRoot);
// Create a <node1> to hold text content.
bstr = SysAllocString(L"node1");
HRCALL(pXMLDom->createElement(bstr,&pe),"");
SysFreeString(bstr);
bstr=NULL;
bstr=SysAllocString(L"some character data");
HRCALL(pe->put_text(bstr), "");
SysFreeString(bstr);
bstr=NULL;
// Append <node1> to <root>.
AppendChildToParent(pe, pRoot);
pe->Release();
pe=NULL;
// Add NEWLINE+TAB for identation before <node2>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsnt, pRoot);
// Create a <node2> to hold a CDATA section.
bstr = SysAllocString(L"node2");
HRCALL(pXMLDom->createElement(bstr,&pe),"create <node2> ");
SysFreeString(bstr);
bstr=NULL;
bstr = SysAllocString(L"<some mark-up text>");
HRCALL(pXMLDom->createCDATASection(bstr,&pcd),"");
SysFreeString(bstr);
bstr=NULL;
if (!pcd) goto clean;
AppendChildToParent(pcd, pe);
pcd->Release();
pcd=NULL;
// Append <node2> to <root>.
AppendChildToParent(pe, pRoot);
pe->Release();
pe=NULL;
// Add NEWLINE+TAB for identation before <node3>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsnt, pRoot);
// Create <node3> to hold a doc fragment with three sub-elements.
bstr = SysAllocString(L"node3");
HRCALL(pXMLDom->createElement(bstr,&pe),"");
SysFreeString(bstr);
bstr=NULL;
// Create a document fragment to hold three sub-elements.
HRCALL(pXMLDom->createDocumentFragment(&pdf), "");
// Add NEWLINE+TAB+TAB for identation before <subnode1>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsntt, pdf);
// Create <subnode1>.
bstr = SysAllocString(L"subnode1");
HRCALL(pXMLDom->createElement(bstr,&peSub), "");
SysFreeString(bstr);
bstr=NULL;
// Add <subnode1> to pdf.
AppendChildToParent(peSub, pdf);
peSub->Release();
peSub=NULL;
// Add NEWLINE+TAB+TAB for identation before <subnode2>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsntt, pdf);
// Create and append <subnode2>.
bstr = SysAllocString(L"subnode2");
HRCALL(pXMLDom->createElement(bstr,&peSub), "");
SysFreeString(bstr);
bstr=NULL;
// Add <subnode1> to pdf.
AppendChildToParent(peSub, pdf);
peSub->Release();
peSub=NULL;
// Add NEWLINE+TAB+TAB for identation before <subnode3>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsntt, pdf);
// Create and append <subnode3>.
bstr = SysAllocString(L"subnode3");
HRCALL(pXMLDom->createElement(bstr,&peSub), "");
SysFreeString(bstr);
bstr=NULL;
if (!peSub) goto clean;
// Add <subnode1> to pdf.
AppendChildToParent(peSub, pdf);
peSub->Release();
peSub=NULL;
// Add NEWLINE+TAB after </subnode> in pdf.
AddWhiteSpaceToNode(pXMLDom, bstr_wsnt, pdf);
// Append pdf to <node3> (pe).
AppendChildToParent(pdf, pe);
// Append <node3> to <root>.
AppendChildToParent(pe, pRoot);
// Add NEWLINE for identation before </root>.
AddWhiteSpaceToNode(pXMLDom, bstr_wsn, pRoot);
HRCALL(pXMLDom->get_xml(&bstr), "dom->get_xml");
dprintf("Dynamically created DOM:\n%S\n", bstr);
VariantClear(&var);
var = VariantString(L"dynamDom.xml");
HRCALL(pXMLDom->save(var), "");
dprintf("DOM saved to dynamDom.xml\n");
clean:
if (bstr) SysFreeString(bstr);
if (bstr1) SysFreeString(bstr1);
if (&var) VariantClear(&var);
if (pXMLDom) pXMLDom->Release();
if (pRoot) pRoot->Release();
if (pe) pe->Release();
if (peSub) peSub->Release();
if (pi) pi->Release();
if (pa) pa->Release();
if (pa1) pa1->Release();
if (pc) pc->Release();
if (pcd) pcd->Release();
if (pdf) pdf->Release();
CoUninitialize();
return 0;
}
To add dynamDOM.cpp to the project
Next, build and run the dynamDOM project. The result should be the output shown in the following topic.