Exemplo n.º 1
0
    //helper function to append a sub node child to a documentfragment with given name and value:
	HRESULT AddSubNodeToDocumentFragment(
		     IXMLDOMDocument* pDOM, 
		     const wchar_t* wszSubNodeName, 
		     const wchar_t* wszSubNodeValue,
		     IXMLDOMDocumentFragment* pdf	// Release is completed outside
		)
	{
		BSTR bstr = NULL;
		IXMLDOMElement* peSub = NULL;

        HRESULT hr = S_OK;
		do
		{
			bstr = SysAllocString(wszSubNodeName);
			HR_SUCCESSCALL( pDOM->createElement(bstr, &peSub), hr );
            SAFE_BSTR_RELEASE(bstr);
			
			bstr=SysAllocString(wszSubNodeValue);
			HR_SUCCESSCALL( peSub->put_text(bstr), hr );
			HR_SUCCESSCALL( AppendChildToParent(peSub, pdf), hr );
		}while(0);

        //release the com object
        SAFE_COM_RELEASE(peSub);
        //release the bstr
        SAFE_BSTR_RELEASE(bstr);

		return hr;
	}
Exemplo n.º 2
0
int DicomImageSet::parseFolder(QString folderName)
{
	QStringList fileList = getAllFiles(folderName);
    HRESULT hr = CoInitialize(NULL);
    if (!SUCCEEDED(hr))
    {
		return NULL;
    }

    hr = S_OK;
    IXMLDOMDocument *pXMLDom = NULL;
    IXMLDOMElement *pRoot = NULL;

    BSTR bstrXML = NULL;
    VARIANT varFileName;
    VariantInit(&varFileName);

	QProgressDialog progress (QString("Parsing all files in %1").arg(folderName), QString("Cancel"), 0, fileList.count());

    CHK_HR(CreateAndInitDOM(&pXMLDom));

    // Create a processing instruction element.
    CHK_HR(CreateAndAddPINode(pXMLDom, L"xml", L"version='1.0'"));
    
    // Create the root element.
    CHK_HR(CreateElement(pXMLDom, L"root", &pRoot));

    // Create an attribute for the <root> element, with name "created" and value "using dom".
	CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"path", folderName.toStdWString().c_str(), pRoot));

    // Add NEWLINE for identation before </root>.
    CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pRoot));
    // add <root> to document
    CHK_HR(AppendChildToParent(pRoot, pXMLDom));

	progress.show();
	for (int i=0; i<fileList.count(); ++i)
	{
		insertFileItem(pXMLDom, pRoot, folderName, fileList[i]);
		progress.setValue(i);
	}

	CHK_HR(VariantFromString(QDir(folderName).filePath(DATASET_FILE_NAME).toStdWString().c_str(), varFileName));
    CHK_HR(pXMLDom->save(varFileName));

CleanUp:
    SAFE_RELEASE(pRoot);
    SysFreeString(bstrXML);
    VariantClear(&varFileName);

    CoUninitialize();
	if (FAILED(hr))
	{
		SAFE_RELEASE(pXMLDom);
		return 0;
	}
	return 1;
}
Exemplo n.º 3
0
int DicomImageSet::insertDTIFileItem(const QString &datasetFolderName, const QString &queryString, const QString &dtiFileName)
{
	HRESULT hr = CoInitialize(NULL);
	if (!SUCCEEDED(hr))
	{
		return 0;
	}
	QString datasetFileName = datasetFolderName+DATASET_FILE_NAME;
	IXMLDOMDocument *pXMLDom = NULL;
	IXMLDOMElement *pNode = NULL, *pParent = NULL;
	BSTR bstrQuery = NULL;
	VARIANT varFileName;
	VARIANT_BOOL varStatus;
	QString queryDTIFile;

	CHK_HR(CreateAndInitDOM(&pXMLDom));
	CHK_HR(VariantFromString(datasetFileName.toStdWString().c_str(), varFileName));
	CHK_HR(pXMLDom->load(varFileName, &varStatus));

	/*queryDTIFile = queryString+QString("/DTI[@file_name = '%1']").arg(dtiFileName);
	bstrQuery = SysAllocString(queryString.toStdWString().c_str());
	CHK_ALLOC(bstrQuery);
	CHK_HR(pXMLDom->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pNode));
	SysFreeString(bstrQuery);
	if (pNode)
	{
		return 1;
	}*/	

	bstrQuery = SysAllocString(queryString.toStdWString().c_str());
	CHK_ALLOC(bstrQuery);
	CHK_HR(pXMLDom->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pParent));
	SysFreeString(bstrQuery);

	if (pParent)
	{
		CHK_HR(CreateElement(pXMLDom, L"DTI", &pNode));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"file_name", dtiFileName.toStdWString().c_str(), pNode));
		CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pParent));
		CHK_HR(AppendChildToParent(pNode, pParent));
		CHK_HR(pXMLDom->save(varFileName));
		return 1;
	}

CleanUp:
	SAFE_RELEASE(pXMLDom);
	SAFE_RELEASE(pNode);
	return 0;
}
Exemplo n.º 4
0
    //put xml file element function
	HRESULT PutXMLFileHead(IXMLDOMDocument* pDOM, IXMLDOMElement** ppRoot)
	{
		  IXMLDOMProcessingInstruction *pi = NULL;
          HRESULT hr = S_OK;
		  do
		  {
			    //create a processing instruction element.
			    _bstr_t header = L"xml";
			    _bstr_t content = L"version='1.0' encoding='utf-8'";
			    HR_SUCCESSCALL( pDOM->createProcessingInstruction(header,content, &pi), hr );
                HR_SUCCESSCALL( AppendChildToParent(pi, pDOM), hr );

			    //create the root element.
			    _bstr_t root = L"VideoStrcuture";
			    HR_SUCCESSCALL( pDOM->createElement(root, ppRoot), hr );
			    HR_SUCCESSCALL( AppendChildToParent(*ppRoot, pDOM), hr );
		
		}while(0);

        //release the com object
		SAFE_COM_RELEASE(pi);

		return hr;
	}    
Exemplo n.º 5
0
// Helper function to create and add a comment to a document node.
HRESULT XMLHelper::CreateAndAddCommentNode(IXMLDOMDocument *pDom, PCWSTR wszComment)
{
    HRESULT hr = S_OK;
    IXMLDOMComment *pComment = NULL;

    BSTR bstrComment = SysAllocString(wszComment);
    CHK_ALLOC(bstrComment);
    
    CHK_HR(pDom->createComment(bstrComment, &pComment));
    CHK_HR(AppendChildToParent(pComment, pDom));

CleanUp:
    SAFE_RELEASE(pComment);
    SysFreeString(bstrComment);
    return hr;
}
Exemplo n.º 6
0
// Helper function to create and append a CDATA node to a parent node.
HRESULT XMLHelper::CreateAndAddCDATANode(IXMLDOMDocument *pDom, PCWSTR wszCDATA, IXMLDOMNode *pParent)
{
    HRESULT hr = S_OK;
    IXMLDOMCDATASection *pCDATA = NULL;

    BSTR bstrCDATA = SysAllocString(wszCDATA);
    CHK_ALLOC(bstrCDATA);

    CHK_HR(pDom->createCDATASection(bstrCDATA, &pCDATA));
    CHK_HR(AppendChildToParent(pCDATA, pParent));

CleanUp:
    SAFE_RELEASE(pCDATA);
    SysFreeString(bstrCDATA);
    return hr;
}
Exemplo n.º 7
0
// Helper function to create and append a text node to a parent node.
HRESULT XMLHelper::CreateAndAddTextNode(IXMLDOMDocument *pDom, PCWSTR wszText, IXMLDOMNode *pParent)
{
    HRESULT hr = S_OK;    
    IXMLDOMText *pText = NULL;

    BSTR bstrText = SysAllocString(wszText);
    CHK_ALLOC(bstrText);

    CHK_HR(pDom->createTextNode(bstrText, &pText));
    CHK_HR(AppendChildToParent(pText, pParent));

CleanUp:
    SAFE_RELEASE(pText);
    SysFreeString(bstrText);
    return hr;
}
Exemplo n.º 8
0
// Helper function to create and add a processing instruction to a document node.
HRESULT XMLHelper::CreateAndAddPINode(IXMLDOMDocument *pDom, PCWSTR wszTarget, PCWSTR wszData)
{
    HRESULT hr = S_OK;
    IXMLDOMProcessingInstruction *pPI = NULL;

    BSTR bstrTarget = SysAllocString(wszTarget);
    BSTR bstrData = SysAllocString(wszData);
    CHK_ALLOC(bstrTarget && bstrData);
    
    CHK_HR(pDom->createProcessingInstruction(bstrTarget, bstrData, &pPI));
    CHK_HR(AppendChildToParent(pPI, pDom));

CleanUp:
    SAFE_RELEASE(pPI);
    SysFreeString(bstrTarget);
    SysFreeString(bstrData);
    return hr;
}
Exemplo n.º 9
0
// Helper function to create and append an element node to a parent node, and pass the newly created
// element node to caller if it wants.
HRESULT XMLHelper::CreateAndAddElementNode(IXMLDOMDocument *pDom, PCWSTR wszName, PCWSTR wszNewline, IXMLDOMNode *pParent, IXMLDOMElement **ppElement)
{
    HRESULT hr = S_OK;
    IXMLDOMElement* pElement = NULL;

    CHK_HR(CreateElement(pDom, wszName, &pElement));
    // Add NEWLINE+TAB for identation before this element.
    CHK_HR(CreateAndAddTextNode(pDom, wszNewline, pParent));
    // Append this element to parent.
    CHK_HR(AppendChildToParent(pElement, pParent));

CleanUp:
    if (ppElement)
        *ppElement = pElement;  // Caller is repsonsible to release this element.
    else
        SAFE_RELEASE(pElement); // Caller is not interested on this element, so release it.

    return hr;
}
Exemplo n.º 10
0
IXMLDOMNode * DicomImageSet::findParentNode(IXMLDOMDocument *pXMLDom, IXMLDOMNode * pRoot, const char * patientsName, const char * patientsId, int acquisitionDate, const char * protocol, int acquisitionNumber)
{
	if (!pXMLDom)
	{
		return NULL;
	}
	
	HRESULT hr = S_OK;
    IXMLDOMElement *pPatient = NULL, *pDate = NULL, *pProtocol = NULL, *pCollection = NULL;
	BSTR bstrQuery = NULL;
	QString strQuery;
	bool nodeExist = false;

	//look for the patient node
	strQuery = QString("root/Patient[@patients_name = '%1' and @patient_id = '%2']").arg(patientsName).arg(patientsId);
	bstrQuery = SysAllocString(strQuery.toStdWString().c_str());
    CHK_ALLOC(bstrQuery);
    CHK_HR(pXMLDom->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pPatient));
    SysFreeString(bstrQuery);
	nodeExist = pPatient;
	if (!nodeExist)
	{
		//create the patient node
		CHK_HR(CreateElement(pXMLDom, L"Patient", &pPatient));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"patients_name", QString(patientsName).toStdWString().c_str(), pPatient));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"patient_id", QString(patientsId).toStdWString().c_str(), pPatient));
		CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pRoot));
		CHK_HR(AppendChildToParent(pPatient, pRoot));
	}
	if (nodeExist)
	{
		//look for the date node
		strQuery = QString("Date[@acquisition_date = '%1']").arg(acquisitionDate);
		bstrQuery = SysAllocString(strQuery.toStdWString().c_str());
		CHK_ALLOC(bstrQuery);
		CHK_HR(pPatient->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pDate));
		SysFreeString(bstrQuery);
		nodeExist = pDate;
	}
	if (!nodeExist)
	{
		CHK_HR(CreateElement(pXMLDom, L"Date", &pDate));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"acquisition_date", QString::number(acquisitionDate).toStdWString().c_str(), pDate));
		CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pPatient));
		CHK_HR(AppendChildToParent(pDate, pPatient));
	}
	if (nodeExist)
	{
		//look for the protocol node
		strQuery = QString("Protocol[@protocol_name = '%1']").arg(protocol);
		bstrQuery = SysAllocString(strQuery.toStdWString().c_str());
		CHK_ALLOC(bstrQuery);
		CHK_HR(pDate->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pProtocol));
		SysFreeString(bstrQuery);
		nodeExist = pProtocol;
	}
	if (!nodeExist)
	{
		CHK_HR(CreateElement(pXMLDom, L"Protocol", &pProtocol));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"protocol_name", QString(protocol).toStdWString().c_str(), pProtocol));
		CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pDate));
		CHK_HR(AppendChildToParent(pProtocol, pDate));
	}
	if (nodeExist)
	{
		//look for the collection node
		strQuery = QString("Collection[@acquisition_number = '%1']").arg(acquisitionNumber);
		bstrQuery = SysAllocString(strQuery.toStdWString().c_str());
		CHK_ALLOC(bstrQuery);
		CHK_HR(pProtocol->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pCollection));
		SysFreeString(bstrQuery);
		nodeExist = pCollection;
	}
	if (!nodeExist)
	{
		CHK_HR(CreateElement(pXMLDom, L"Collection", &pCollection));
		CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"acquisition_number", QString::number(acquisitionNumber).toStdWString().c_str(), pCollection));
		CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pProtocol));
		CHK_HR(AppendChildToParent(pCollection, pProtocol));
	}

CleanUp:
	SAFE_RELEASE(pPatient);
	SAFE_RELEASE(pDate);
	SAFE_RELEASE(pProtocol);

	if(SUCCEEDED(hr))
	{
		return pCollection;
	}
	SAFE_RELEASE(pCollection);
	return NULL;
}
Exemplo n.º 11
0
	//add Id array to a document fragment node
	HRESULT AddIdsNode(
		    IXMLDOMDocument* pDOM, 
		    BSTR indentBstr,
		    const wchar_t* wszIdsNodeName, 
		    const wchar_t* wszIdsNodeAttribute,
		    const wchar_t* wszIdNode,
		    const std::vector<int>& ids, 
		    IXMLDOMDocumentFragment* pdf	// Release is completed outside
		)
	{
		VARIANT var;
		BSTR bstr = NULL;
		BSTR bstr_wst = SysAllocString(L"\t");
		IXMLDOMElement* pe = NULL;
		IXMLDOMDocumentFragment* pdfSub = NULL;
		IXMLDOMAttribute *pa = NULL;
		IXMLDOMAttribute *pa1 = NULL;

        HRESULT hr = S_OK;
		do
		{
			//create a Node to hold ids.
			bstr = SysAllocString(wszIdsNodeName);
			HR_SUCCESSCALL( pDOM->createElement(bstr, &pe), hr );
			SAFE_BSTR_RELEASE(bstr);

			//create a attribute for the <wszIdsNodeName> element, and
			//assign the element num as the attribute value.
			
			//get ids num string
			size_t idsNum = ids.size();
			const int radix = 10;
			const size_t sizeOfstr = 30;
			wchar_t wszIdsNumString[sizeOfstr] = {0};
			_ultow_s(static_cast<unsigned long>(idsNum), wszIdsNumString, sizeOfstr, radix);

			//put num string into attribute
			bstr = SysAllocString(wszIdsNodeAttribute);
			VariantInit(&var);
			V_BSTR(&var) = SysAllocString(wszIdsNumString);
			V_VT(&var) = VT_BSTR;

			HR_SUCCESSCALL( pDOM->createAttribute(bstr, &pa), hr );
			HR_SUCCESSCALL( pa->put_value(var), hr );
			HR_SUCCESSCALL( pe->setAttributeNode(pa, &pa1), hr );

			//create a document fragment to hold ids sub-elements.
			HR_SUCCESSCALL( pDOM->createDocumentFragment(&pdfSub), hr );

			//add ids to pdfSub
			for( size_t i=0; i < idsNum; ++i )
			{
				 int id = ids[i];
				 WCHAR wszIdString[sizeOfstr] = {0};
				 _itow_s(id, wszIdString, sizeOfstr, radix);

				 //add white space before <id>
				 HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
				 HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );
				 HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, wszIdNode, wszIdString, pdfSub), hr );
			}

            //test whether it is successful in "add ids to pdfSub"
			HR_SUCCESSCALL( hr, hr );

			//add ids array to document fragment node
			HR_SUCCESSCALL( AppendChildToParent(pdfSub, pe), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pe), hr );
			HR_SUCCESSCALL( AppendChildToParent(pe, pdf), hr );
			
		}while(0);

        //release the com objects
		SAFE_COM_RELEASE(pa1);
		SAFE_COM_RELEASE(pa);
		SAFE_COM_RELEASE(pdfSub);
		SAFE_COM_RELEASE(pe);

		//release the bstr and variant
        SAFE_BSTR_RELEASE(bstr);
        SAFE_BSTR_RELEASE(bstr_wst);
        VariantClear(&var);

		return hr;
	}
Exemplo n.º 12
0
    //add boundary to shot or sub shot fragment node
    HRESULT AddBoundaryNodeToDocumentFragment(
		   IXMLDOMDocument* pDOM, 
		   BSTR indentBstr,
		   IXMLDOMDocumentFragment* pdf,   // Release is completed outside
		   unsigned int bgnFrameId, unsigned int endFrameId, 
		   __int64 bgnFrameTime, __int64 endFrameTime)
	{
		BSTR bstr = NULL;
		BSTR bstr_wst = SysAllocString(L"\t");
		IXMLDOMElement* pe = NULL;
		IXMLDOMDocumentFragment* pdfSub = NULL;

        HRESULT hr = S_OK;
		do
		{
			//create a Node to hold boundary.
			bstr = SysAllocString(L"Boundary");
			HR_SUCCESSCALL( pDOM->createElement(bstr, &pe), hr );
			SAFE_BSTR_RELEASE(bstr);

			//create a document fragment to hold boundary's sub-elements.
			HR_SUCCESSCALL( pDOM->createDocumentFragment(&pdfSub), hr );

			//add sub elements to pdfSub

			//add white space before <BgnFrameId>
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );

			const int radix = 10;
			const size_t sizeOfstr = 30;
			wchar_t wszBgnFrmIdString[sizeOfstr] = {0};
			_itow_s(bgnFrameId, wszBgnFrmIdString, sizeOfstr, radix);
			HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"BgnFrameId", wszBgnFrmIdString, pdfSub), hr );

			//<EndFrameId>
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );

			wchar_t wszEndFrmIdString[sizeOfstr] = {0};
			_itow_s(endFrameId, wszEndFrmIdString, sizeOfstr, radix);
			HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"EndFrameId", wszEndFrmIdString, pdfSub), hr );

			//<BgnFrameTime>
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );

            //begintime
			wchar_t wszBgnFrmTimeString[sizeOfstr*2] = {0};
			_i64tow_s(bgnFrameTime, wszBgnFrmTimeString, sizeOfstr*2, 10);
			HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"BgnFrameTime", wszBgnFrmTimeString, pdfSub), hr );

			//<EndFrameId>
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pdfSub), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, bstr_wst, pdfSub), hr );

            //endtime
			wchar_t wszEndFrmTimeString[sizeOfstr*2] = {0};
			_i64tow_s(endFrameTime, wszEndFrmTimeString, sizeOfstr*2, 10);
			HR_SUCCESSCALL( AddSubNodeToDocumentFragment(pDOM, L"EndFrameTime", wszEndFrmTimeString, pdfSub), hr );

			//add Boundary to document fragment node
			HR_SUCCESSCALL( AppendChildToParent(pdfSub, pe), hr );
			HR_SUCCESSCALL( AddWhiteSpaceToNode(pDOM, indentBstr, pe), hr );
			HR_SUCCESSCALL( AppendChildToParent(pe, pdf), hr );
						
		}while(0);

		//release com object
		SAFE_COM_RELEASE(pdfSub);
		SAFE_COM_RELEASE(pe);
        //release bstr
        SAFE_BSTR_RELEASE(bstr);
        SAFE_BSTR_RELEASE(bstr_wst);
		
		return hr;
	}
Exemplo n.º 13
-1
void dynamDOM()
{
    HRESULT hr = S_OK;
    IXMLDOMDocument *pXMLDom = NULL;
    IXMLDOMElement *pRoot = NULL;
    IXMLDOMElement *pNode = NULL;
    IXMLDOMElement *pSubNode = NULL;
    IXMLDOMDocumentFragment *pDF = NULL;

    BSTR bstrXML = NULL;
    VARIANT varFileName;
    VariantInit(&varFileName);

    CHK_HR(CreateAndInitDOM(&pXMLDom));

    // Create a processing instruction element.
    CHK_HR(CreateAndAddPINode(pXMLDom, L"xml", L"version='1.0'"));

    // Create a comment element.
    CHK_HR(CreateAndAddCommentNode(pXMLDom, L"sample xml file created using XML DOM object."));

    // Create the root element.
    CHK_HR(CreateElement(pXMLDom, L"root", &pRoot));

    // Create an attribute for the <root> element, with name "created" and value "using dom".
    CHK_HR(CreateAndAddAttributeNode(pXMLDom, L"created", L"using dom", pRoot));

    // Next, we will create and add three nodes to the <root> element.
    // Create a <node1> to hold text content.
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"node1", L"\n\t", pRoot, &pNode));
    CHK_HR(CreateAndAddTextNode(pXMLDom, L"some character data", pNode));
    SAFE_RELEASE(pNode);

    // Create a <node2> to hold a CDATA section.
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"node2", L"\n\t", pRoot, &pNode));
    CHK_HR(CreateAndAddCDATANode(pXMLDom, L"<some mark-up text>", pNode));
    SAFE_RELEASE(pNode);

    // Create <node3> to hold a doc fragment with three sub-elements.
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"node3", L"\n\t", pRoot, &pNode));

    // Create a document fragment to hold three sub-elements.
    CHK_HR(pXMLDom->createDocumentFragment(&pDF));

    // Create 3 subnodes.
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"subNode1", L"\n\t\t", pDF));
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"subNode2", L"\n\t\t", pDF));
    CHK_HR(CreateAndAddElementNode(pXMLDom, L"subNode3", L"\n\t\t", pDF));
    CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n\t", pDF));

    // Append pDF to <node3>.
    CHK_HR(AppendChildToParent(pDF, pNode));
    SAFE_RELEASE(pNode);

    // Add NEWLINE for identation before </root>.
    CHK_HR(CreateAndAddTextNode(pXMLDom, L"\n", pRoot));
    // add <root> to document
    CHK_HR(AppendChildToParent(pRoot, pXMLDom));

    CHK_HR(pXMLDom->get_xml(&bstrXML));
    wprintf(L"Dynamically created DOM:\n%s\n", bstrXML);

    CHK_HR(VariantFromString(L"dynamDOM.xml", varFileName));
    CHK_HR(pXMLDom->save(varFileName));
    wprintf(L"DOM saved to dynamDOM.xml\n");

CleanUp:
    SAFE_RELEASE(pXMLDom);
    SAFE_RELEASE(pRoot);
    SAFE_RELEASE(pNode);
    SAFE_RELEASE(pDF);
    SAFE_RELEASE(pSubNode);
    SysFreeString(bstrXML);
    VariantClear(&varFileName);
}