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;
}
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;
}
QStringList DicomImageSet::getOrderedDcmFiles(const QString &datasetFileName, const QString & queryString)
{
    HRESULT hr = S_OK;
    IXMLDOMDocument *pXMLDom = NULL;
    IXMLDOMNodeList *pFileNodes = NULL;
    VARIANT_BOOL varStatus;
    VARIANT varFileName;
	BSTR bstrQuery;

	QStringList fileList;

    CHK_HR(CreateAndInitDOM(&pXMLDom));

	CHK_HR(VariantFromString(datasetFileName.toStdWString().c_str(), varFileName));
    CHK_HR(pXMLDom->load(varFileName, &varStatus));
    if (varStatus != VARIANT_TRUE)
    {
        CHK_HR(ReportParseError(pXMLDom, "Failed to load DOM from stocks.xml."));
    }

    bstrQuery = SysAllocString(queryString.toStdWString().c_str());
    CHK_ALLOC(bstrQuery);
    CHK_HR(pXMLDom->selectNodes(bstrQuery, &pFileNodes));
	if (pFileNodes)
	{
		long nFiles;
		CHK_HR(pFileNodes->get_length(&nFiles));
		for (long i=0; i<nFiles; ++i)
		{
			VARIANT varValue;
			IXMLDOMNode * pFile = NULL;
			CHK_HR(pFileNodes->get_item(i, &pFile));
			CHK_HR(GetAttributeFromNode(pFile, L"path", &varValue));
			fileList <<QString::fromWCharArray(_bstr_t(varValue));
			SAFE_RELEASE(pFile);
		}
	}

CleanUp:
	SAFE_RELEASE(pXMLDom);
	SAFE_RELEASE(pFileNodes);
	return fileList;
}
QString DicomImageSet::getDTIFileName(const QString &datasetFolderName, const QString &queryString)
{
	QString datasetFileName = datasetFolderName+DATASET_FILE_NAME;
	HRESULT hr = S_OK;
	IXMLDOMDocument *pXMLDom = NULL;
	IXMLDOMNode *pFileNode = NULL;
	VARIANT_BOOL varStatus;
	VARIANT varFileName;
	BSTR bstrQuery;

	QStringList fileList;

	CHK_HR(CreateAndInitDOM(&pXMLDom));

	CHK_HR(VariantFromString(datasetFileName.toStdWString().c_str(), varFileName));
	CHK_HR(pXMLDom->load(varFileName, &varStatus));
	if (varStatus != VARIANT_TRUE)
	{
		CHK_HR(ReportParseError(pXMLDom, "Failed to load DOM from stocks.xml."));
	}

	bstrQuery = SysAllocString(QString(queryString+"/DTI").toStdWString().c_str());
	CHK_ALLOC(bstrQuery);
	CHK_HR(pXMLDom->selectSingleNode(bstrQuery, &pFileNode));
	if (pFileNode)
	{
		VARIANT varValue;
		CHK_HR(GetAttributeFromNode(pFileNode, L"file_name", &varValue));
		return QString::fromWCharArray(_bstr_t(varValue));
	}

CleanUp:
	SAFE_RELEASE(pXMLDom);
	SAFE_RELEASE(pFileNode);
	return QString();
}
int DicomImageSet::readDatasetFile(const QString &datasetFileName, QTreeWidget *treeWidget)
{
    HRESULT hr = S_OK;
    IXMLDOMDocument *pXMLDom = NULL;
    IXMLDOMNodeList *pPatients = NULL;
    IXMLDOMNode *pPatient = NULL;
	DOMNodeType nodeType;
    VARIANT_BOOL varStatus;
    VARIANT varFileName;
	VARIANT varValue;
	BSTR bstrQuery;

    VariantInit(&varFileName);
    VariantInit(&varValue);

	QString queryPatient, queryDate, queryProtocol, queryCollection;

    CHK_HR(CreateAndInitDOM(&pXMLDom));

	CHK_HR(VariantFromString(datasetFileName.toStdWString().c_str(), varFileName));
    CHK_HR(pXMLDom->load(varFileName, &varStatus));
    if (varStatus != VARIANT_TRUE)
    {
        CHK_HR(ReportParseError(pXMLDom, "Failed to load DOM from stocks.xml."));
    }

	treeWidget->clear();
	treeWidget->setColumnCount(1);
	CHK_HR(pXMLDom->getElementsByTagName(L"Patient", &pPatients));
	if (pPatients)
	{
		long nPatients;
		CHK_HR(pPatients->get_length(&nPatients));
		for (long i=0; i<nPatients; ++i)
		{
			CHK_HR(pPatients->get_item(i, &pPatient));
			CHK_HR(GetAttributeFromNode(pPatient, L"patients_name", &varValue));
			queryPatient = QString::fromWCharArray(_bstr_t(varValue));
			QTreeWidgetItem * patientItem = new QTreeWidgetItem(treeWidget, QStringList(queryPatient));
			patientItem->setExpanded(true);

			IXMLDOMNodeList * pDates = NULL;
			CHK_HR(pPatient->get_childNodes(&pDates));
			long nDates;
			CHK_HR(pDates->get_length(&nDates));
			for (long j=0; j<nDates; ++j)
			{
				IXMLDOMNode * pDate = NULL;
				CHK_HR(pDates->get_item(j, &pDate));
				CHK_HR(pDate->get_nodeType(&nodeType));
				if(nodeType!=NODE_ELEMENT)
				{
					continue;
				}
				CHK_HR(GetAttributeFromNode(pDate, L"acquisition_date", &varValue));
				queryDate = QString::fromWCharArray(_bstr_t(varValue));
				int intDate = queryDate.toInt();
				QDate date = (QDate::fromString("1900-01-01", "yyyy-MM-dd")).addDays(intDate-693962);
				QTreeWidgetItem * dateItem = new QTreeWidgetItem(patientItem, QStringList(date.toString("yyyy-MM-dd")));
				dateItem->setExpanded(true);

				IXMLDOMNodeList * pProtocols = NULL;
				CHK_HR(pDate->get_childNodes(&pProtocols));
				long nProtocols;
				CHK_HR(pProtocols->get_length(&nProtocols));
				for (long j=0; j<nProtocols; ++j)
				{
					IXMLDOMNode * pProtocol = NULL;
					CHK_HR(pProtocols->get_item(j, &pProtocol));
					CHK_HR(pProtocol->get_nodeType(&nodeType));
					if(nodeType!=NODE_ELEMENT)
					{
						continue;
					}
					CHK_HR(GetAttributeFromNode(pProtocol, L"protocol_name", &varValue));
					queryProtocol = QString::fromWCharArray(_bstr_t(varValue));
					QTreeWidgetItem * protocolItem = new QTreeWidgetItem(dateItem, QStringList(queryProtocol));
					protocolItem->setExpanded(true);

					IXMLDOMNodeList * pCollections = NULL;
					CHK_HR(pProtocol->get_childNodes(&pCollections));
					long nCollections;
					CHK_HR(pCollections->get_length(&nCollections));
					for (long j=0; j<nCollections; ++j)
					{
						IXMLDOMNode * pCollection = NULL;
						CHK_HR(pCollections->get_item(j, &pCollection));
						CHK_HR(pCollection->get_nodeType(&nodeType));
						if(nodeType!=NODE_ELEMENT)
						{
							continue;
						}
						CHK_HR(GetAttributeFromNode(pCollection, L"acquisition_number", &varValue));
						queryCollection = QString::fromWCharArray(_bstr_t(varValue));
						QTreeWidgetItem * collectionItem = new QTreeWidgetItem(protocolItem);
						QString queryStr = QString("root/Patient[@patients_name = '%1']/Date[@acquisition_date = '%2']/Protocol[@protocol_name = '%3']/Collection[@acquisition_number = '%4']")
							.arg(queryPatient).arg(queryDate).arg(queryProtocol).arg(queryCollection);

						IXMLDOMElement * pDtiNode = NULL;
						bstrQuery = SysAllocString(QString(queryStr+"/DTI").toStdWString().c_str());
						CHK_ALLOC(bstrQuery);
						CHK_HR(pXMLDom->selectSingleNode(bstrQuery, (IXMLDOMNode**)&pDtiNode));
						SysFreeString(bstrQuery);
						if (pDtiNode)
						{
							collectionItem->setText(0,queryCollection+"*");
						} else
						{
							collectionItem->setText(0, queryCollection);
						}

						collectionItem->setData(0, Qt::UserRole, queryStr);
						collectionItem->setExpanded(true);


						protocolItem->addChild(collectionItem);
						SAFE_RELEASE(pCollection);
					}

					dateItem->addChild(protocolItem);
					SAFE_RELEASE(pProtocol);
				}

				patientItem->addChild(dateItem);
				SAFE_RELEASE(pDate);
			}
			treeWidget->insertTopLevelItem(i, patientItem);
			SAFE_RELEASE(pPatient);
		}
	}

CleanUp:
    SAFE_RELEASE(pXMLDom);
    SAFE_RELEASE(pPatients);
    SAFE_RELEASE(pPatient);
    VariantClear(&varFileName);

	return SUCCEEDED(hr);
}
void queryNodes()
{
    HRESULT hr = S_OK;
    IXMLDOMDocument *pXMLDom = NULL;
    IXMLDOMNodeList *pNodes = NULL;
    IXMLDOMNode *pNode = NULL;

    BSTR bstrQuery1 = NULL;
    BSTR bstrQuery2 = NULL;
    BSTR bstrNodeName = NULL;
    BSTR bstrNodeValue = NULL;
    VARIANT_BOOL varStatus;
    VARIANT varFileName;
    VariantInit(&varFileName);

    CHK_HR(CreateAndInitDOM(&pXMLDom));

    CHK_HR(VariantFromString(L"stocks.xml", varFileName));
    CHK_HR(pXMLDom->load(varFileName, &varStatus));
    if (varStatus != VARIANT_TRUE)
    {
        CHK_HR(ReportParseError(pXMLDom, "Failed to load DOM from stocks.xml."));
    }

    // Query a single node.
    bstrQuery1 = SysAllocString(L"//stock[1]/*");
    CHK_ALLOC(bstrQuery1);
    CHK_HR(pXMLDom->selectSingleNode(bstrQuery1, &pNode));
    if (pNode)
    {
        printf("Result from selectSingleNode:\n");
        CHK_HR(pNode->get_nodeName(&bstrNodeName));
        printf("Node, <%S>:\n", bstrNodeName);
        SysFreeString(bstrNodeName);

        CHK_HR(pNode->get_xml(&bstrNodeValue));
        printf("\t%S\n\n", bstrNodeValue);
        SysFreeString(bstrNodeValue);
        SAFE_RELEASE(pNode);
    }
    else
    {
        CHK_HR(ReportParseError(pXMLDom, "Error while calling selectSingleNode."));
    }

    // Query a node-set.
    bstrQuery2 = SysAllocString(L"//stock[1]/*");
    CHK_ALLOC(bstrQuery2);
    CHK_HR(pXMLDom->selectNodes(bstrQuery2, &pNodes));
    if(pNodes)
    {
        printf("Results from selectNodes:\n");
        //get the length of node-set
        long length;
        CHK_HR(pNodes->get_length(&length));
        for (long i = 0; i < length; i++)
        {
            CHK_HR(pNodes->get_item(i, &pNode));
            CHK_HR(pNode->get_nodeName(&bstrNodeName));
			/*if(0== wcscmp(bstrNodeValue, L"symbol"))
			{
				 
			}
           */
			printf("Node (%d), <%S>:\n", i, bstrNodeName);
            SysFreeString(bstrNodeName);

            CHK_HR(pNode->get_xml(&bstrNodeValue));
			
            printf("\t%S\n", bstrNodeValue);
            SysFreeString(bstrNodeValue);
            SAFE_RELEASE(pNode);
        }
    }
    else
    {
        CHK_HR(ReportParseError(pXMLDom, "Error while calling selectNodes."));
    }

CleanUp:
    SAFE_RELEASE(pXMLDom);
    SAFE_RELEASE(pNodes);
    SAFE_RELEASE(pNode);
    SysFreeString(bstrQuery1);
    SysFreeString(bstrQuery2);
    SysFreeString(bstrNodeName);
    SysFreeString(bstrNodeValue);
    VariantClear(&varFileName);
}
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);
}