You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
6.3 KiB
272 lines
6.3 KiB
|
|
#include <wininetp.h>
|
|
|
|
#include "xmlwrapper.h"
|
|
|
|
|
|
IXMLDOMDocument *createXMLDocument() {
|
|
|
|
IXMLDOMDocument *pDocument = NULL;
|
|
|
|
HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**) &pDocument);
|
|
|
|
/* if COM library was not initialized, retry after init */
|
|
if (hr==CO_E_NOTINITIALIZED) {
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**) &pDocument);
|
|
}
|
|
|
|
return pDocument;
|
|
}
|
|
|
|
IXMLDOMDocument *parseXMLDocument(char *pszFileName) {
|
|
|
|
IXMLDOMDocument *document = createXMLDocument();
|
|
|
|
if (!document)
|
|
return NULL;
|
|
|
|
/* Do not perform DTD or schema validation on P3P files */
|
|
document->put_validateOnParse(FALSE);
|
|
|
|
/* Open the file */
|
|
HANDLE hf = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
if (hf!=INVALID_HANDLE_VALUE) {
|
|
|
|
/* Obtain stream from the XML document and write out
|
|
contents of the file to stream */
|
|
IStream *pStream = NULL;
|
|
|
|
HRESULT hr = document->QueryInterface(IID_IStream, (void**) &pStream);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
unsigned char xmldata[1024];
|
|
DWORD dwBytes, dwWritten;
|
|
|
|
do {
|
|
ReadFile(hf, xmldata, sizeof(xmldata), &dwBytes, NULL);
|
|
pStream->Write(xmldata, dwBytes, &dwWritten);
|
|
if (dwBytes!=dwWritten)
|
|
break;
|
|
}
|
|
while (dwBytes>0);
|
|
|
|
pStream->Release();
|
|
}
|
|
|
|
CloseHandle(hf);
|
|
}
|
|
|
|
return document;
|
|
};
|
|
|
|
int defineAttributes(TreeNode *pCurrent, IXMLDOMNode *pXMLnode) {
|
|
|
|
int cAttribute = 0;
|
|
|
|
IXMLDOMNamedNodeMap *pAttributeMap = NULL;
|
|
|
|
HRESULT hr = pXMLnode->get_attributes(&pAttributeMap);
|
|
|
|
if (SUCCEEDED(hr) && pAttributeMap) {
|
|
|
|
long cItems;
|
|
IXMLDOMNode *pNode;
|
|
IXMLDOMAttribute *pAttribute;
|
|
|
|
pAttributeMap->get_length(&cItems);
|
|
|
|
for (int i=0; i<cItems; i++) {
|
|
|
|
pNode = pAttribute = NULL;
|
|
pAttributeMap->get_item(i, &pNode);
|
|
|
|
if (pNode) {
|
|
|
|
pNode->QueryInterface(IID_IXMLDOMAttribute, (void**) &pAttribute);
|
|
|
|
if (pAttribute) {
|
|
|
|
BSTR bsName = NULL;
|
|
pAttribute->get_name(&bsName);
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
pAttribute->get_value(&var);
|
|
|
|
char *pszName = unicode2ASCII(bsName);
|
|
char *pszValue = (var.vt==VT_BSTR) ? unicode2ASCII(var.bstrVal) : NULL;
|
|
|
|
pCurrent->defineAttribute(pszName, pszValue);
|
|
|
|
delete [] pszName;
|
|
delete [] pszValue;
|
|
|
|
SysFreeString(bsName);
|
|
VariantClear(&var);
|
|
|
|
pAttribute->Release();
|
|
cAttribute++;
|
|
}
|
|
|
|
pNode->Release();
|
|
}
|
|
}
|
|
|
|
pAttributeMap->Release();
|
|
}
|
|
|
|
return cAttribute;
|
|
}
|
|
|
|
TreeNode *createXMLtree(IXMLDOMNode *pXMLnode, TreeNode *pParent = NULL) {
|
|
|
|
HRESULT hr;
|
|
|
|
if (!pXMLnode)
|
|
return NULL;
|
|
|
|
DOMNodeType dt;
|
|
pXMLnode->get_nodeType(&dt);
|
|
|
|
if (dt!=NODE_ELEMENT &&
|
|
dt!=NODE_TEXT &&
|
|
dt!=NODE_CDATA_SECTION)
|
|
return NULL;
|
|
|
|
TreeNode *pTree = new TreeNode();
|
|
pTree->nodetype = dt;
|
|
|
|
switch (dt) {
|
|
|
|
case NODE_ELEMENT: {
|
|
|
|
|
|
IXMLDOMElement *pElement;
|
|
hr = pXMLnode->QueryInterface(IID_IXMLDOMElement, (void**) &pElement);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
BSTR bsName = NULL;
|
|
pElement->get_tagName(&bsName);
|
|
|
|
if (bsName) {
|
|
char *pszTagName = unicode2ASCII(bsName);
|
|
pTree->setContent(pszTagName);
|
|
delete [] pszTagName;
|
|
SysFreeString(bsName);
|
|
}
|
|
|
|
pElement->Release();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case NODE_TEXT:
|
|
case NODE_CDATA_SECTION: {
|
|
|
|
IXMLDOMCharacterData *pCharData = NULL;
|
|
hr = pXMLnode->QueryInterface(IID_IXMLDOMCharacterData, (void**) &pCharData);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
BSTR bsData = NULL;
|
|
pCharData->get_data(&bsData);
|
|
|
|
if (bsData) {
|
|
pTree->pszContents = unicode2ASCII(bsData);
|
|
SysFreeString(bsData);
|
|
}
|
|
pCharData->Release();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Enumerate attributes */
|
|
defineAttributes(pTree, pXMLnode);
|
|
|
|
/* Recursively create nodes for descendants */
|
|
TreeNode *pLast = NULL;
|
|
IXMLDOMNode *pChild = NULL;
|
|
|
|
pXMLnode->get_firstChild(&pChild);
|
|
|
|
while (pChild) {
|
|
|
|
if (TreeNode *pDescendant = createXMLtree(pChild, pTree)) {
|
|
|
|
if (pLast)
|
|
pLast->pSibling = pDescendant;
|
|
pLast = pDescendant;
|
|
|
|
if (! pTree->pDescendant)
|
|
pTree->pDescendant = pDescendant;
|
|
}
|
|
|
|
IXMLDOMNode *pTemp = pChild;
|
|
hr = pChild->get_nextSibling(&pChild);
|
|
pTemp->Release();
|
|
if (!SUCCEEDED(hr))
|
|
break;
|
|
}
|
|
|
|
return pTree;
|
|
}
|
|
|
|
|
|
TreeNode *createXMLtree(IXMLDOMDocument *pDocument) {
|
|
|
|
IXMLDOMElement *pElement = NULL;
|
|
TreeNode *pRoot = NULL;
|
|
|
|
HRESULT hr = pDocument->get_documentElement(&pElement);
|
|
|
|
if (pElement) {
|
|
|
|
pRoot = createXMLtree(pElement);
|
|
pElement->Release();
|
|
}
|
|
|
|
return pRoot;
|
|
}
|
|
|
|
|
|
/*
|
|
Utility functions
|
|
*/
|
|
|
|
char *unicode2ASCII(XMLchar *pwszSource) {
|
|
|
|
if (!pwszSource)
|
|
return NULL;
|
|
|
|
char *pszDestination = NULL;
|
|
|
|
int cRequired = WideCharToMultiByte(CP_ACP, 0, pwszSource, -1, pszDestination, 0, NULL, NULL);
|
|
|
|
if (cRequired>0 && (pszDestination = new char[cRequired]))
|
|
WideCharToMultiByte(CP_ACP, 0, pwszSource, -1, pszDestination, cRequired, NULL, NULL);
|
|
|
|
return pszDestination;
|
|
}
|
|
|
|
BSTR ASCII2unicode(const char *pszSource) {
|
|
|
|
int cRequired = MultiByteToWideChar(CP_ACP, 0, pszSource, -1, NULL, 0);
|
|
|
|
if (cRequired==0)
|
|
return NULL;
|
|
|
|
BSTR bsResult = SysAllocStringLen(NULL, cRequired);
|
|
|
|
if (bsResult)
|
|
MultiByteToWideChar(CP_ACP, 0, pszSource, -1, bsResult, cRequired);
|
|
|
|
return bsResult;
|
|
}
|
|
|