/* * (c) Copyright Ascensio System SIA 2010-2014 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, * EU, LV-1021. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ #pragma once #import rename_namespace("XML") #ifdef _USE_XMLLITE_READER_ #pragma comment(lib, "XmlLite.lib") #include "XmlLite.h" #endif #include "Utils.h" namespace MSXML { struct __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) DOMDocument; struct __declspec(uuid("f5078f1b-c551-11d3-89b9-0000f81fe221")) DOMDocument26; struct __declspec(uuid("f5078f32-c551-11d3-89b9-0000f81fe221")) DOMDocument30; struct __declspec(uuid("88d969c0-f192-11d4-a65f-0040963251e5")) DOMDocument40; struct __declspec(uuid("88d969e5-f192-11d4-a65f-0040963251e5")) DOMDocument50; struct __declspec(uuid("88d96a05-f192-11d4-a65f-0040963251e5")) DOMDocument60; } #define MSXMLDocument __uuidof(MSXML2::DOMDocument60) namespace XmlUtils { static CString GetNodeAttrib(XML::IXMLDOMNodePtr node, const CString& attrib, const CString& def = _T("")) { try { if (node == NULL || attrib.GetLength() < 1) return def; _bstr_t x = attrib; IXMLDOMNamedNodeMapPtr attributes = node->attributes; if (attributes == NULL) return def; IXMLDOMNodePtr tempNode; attributes->getNamedItem(x, &tempNode); if(tempNode == NULL) return def; BSTR str; tempNode->get_text(&str); CString s = CString(str); SysFreeString(str); return s; } catch (...) { } return def; } static CString GetNodeAttribExt(XML::IXMLDOMNodePtr node, const CString& attrib, const CString& def = _T("")) { try { if (node == NULL || attrib.GetLength() < 1) return def; _bstr_t x = attrib; if (node->attributes == NULL || node->attributes->getNamedItem(x) == NULL) return def; VARIANT var; node->attributes->getNamedItem(x)->get_nodeValue(&var); if (VT_BSTR == var.vt) { CString s = (CString)var.bstrVal; VariantClear(&var); return s; } VariantClear(&var); } catch (...) { } return def; } static CString GetNodeText(XML::IXMLDOMNodePtr node, const CString& def = _T("")) { try { if (node == NULL) return def; CString s; s = node->text.GetBSTR(); return s; } catch (...) { } return def; } static CString GetNodeXml(XML::IXMLDOMNodePtr node, const CString& subnode, const CString& def = _T("")) { try { if (node == NULL) return def; CString s; if (subnode.GetLength() < 1) s = node->xml.GetBSTR(); else { _bstr_t x = subnode; s = node->selectSingleNode(x)->xml.GetBSTR(); } return s; } catch (...) { } return def; } static CString GetNodeValue(XML::IXMLDOMNodePtr node, const CString& subnode, const CString& def = _T("")) { try { if (node == NULL || subnode.GetLength() < 1) return def; _bstr_t x = subnode; if (node->selectSingleNode(x) == NULL) return def; CString s; s = node->selectSingleNode(x)->text.GetBSTR(); return s; } catch (...) { } return def; } static CString GetNodeValueExt(XML::IXMLDOMNodePtr ptrNode, const CString& sDef = _T("")) { try { if (ptrNode == NULL) return sDef; CString sPath = _T("./text()"); XML::IXMLDOMNodeList* pChildTextNodeList = NULL; BSTR bsPath = sPath.AllocSysString(); ptrNode->raw_selectNodes(bsPath, &pChildTextNodeList); SysFreeString(bsPath); if (NULL!=pChildTextNodeList) { CString sRet; long lCount = 0; pChildTextNodeList->get_length(&lCount); for (long lIndex = 0; lIndex < lCount; lIndex++) { XML::IXMLDOMNode *pChildTextNode = NULL; pChildTextNodeList->get_item(lIndex, &pChildTextNode); if (NULL==pChildTextNode) continue; VARIANT vt; pChildTextNode->get_nodeValue(&vt); pChildTextNode->Release(); CString sValue; if (VT_BSTR == vt.vt) sValue = vt.bstrVal; VariantClear(&vt); sRet += sValue; } pChildTextNodeList->Release(); return sRet; } } catch (...) { } return sDef; } static BOOL GetNodeTextTyped(XML::IXMLDOMNodePtr node, _variant_t* variant, const CString& type = _T("bin.base64")) { try { if (node == NULL) return FALSE; BSTR bstrType = type.AllocSysString(); node->put_dataType(bstrType); SysFreeString(bstrType); *variant = node->nodeTypedValue; return TRUE; } catch (...) { } return FALSE; } static CString GetNodeAttrib(XML::IXMLDOMNodeListPtr nodes, int index, const CString& attrib, const CString& def = _T("")) { try { if (nodes == NULL || index < 0 || index >= nodes->length) return def; CString s = GetNodeAttrib(nodes->item[index], attrib, def); return s; } catch (...) { } return def; } static CString GetNodeText(XML::IXMLDOMNodeListPtr nodes, int index, const CString& def = _T("")) { try { if (nodes == NULL || index < 0 || index >= nodes->length) return def; CString s = GetNodeText(nodes->item[index], def); return s; } catch (...) { } return def; } static CString GetNodeXml(XML::IXMLDOMNodeListPtr nodes, int index, const CString& def = _T("")) { try { if (nodes == NULL || index < 0 || index >= nodes->length) return def; CString s = GetNodeXml(nodes->item[index], def); return s; } catch (...) { } return def; } static CString GetNodeValue(XML::IXMLDOMNodeListPtr nodes, int index, const CString& subnode, const CString& def = _T("")) { try { if (nodes == NULL || index < 0 || index >= nodes->length) return def; CString s = GetNodeValue(nodes->item[index], subnode, def); return s; } catch (...) { } return def; } static BOOL GetNodeTextTyped(XML::IXMLDOMNodeListPtr nodes, int index, _variant_t* variant, const CString& type = _T("bin.base64")) { try { if (nodes == NULL || index < 0 || index >= nodes->length) return FALSE; return GetNodeTextTyped(nodes->item[index], variant, type); } catch (...) { } return FALSE; } class CXmlWriter { CString m_str; public: CXmlWriter() { m_str.Empty(); } CString GetXmlString() { return m_str; } void SetXmlString(const CString& strValue) { m_str = strValue; } BOOL SaveToFile(const CString& strFilePath, BOOL bEncodingToUTF8 = FALSE) { FILE* pFile = _tfopen(strFilePath, _T("wt")); if (!pFile) return FALSE; CStringA str; str = m_str; if (bEncodingToUTF8) #ifdef _UNICODE str = EncodingUnicodeToUTF8(); #else str = EncodingASCIIToUTF8(); #endif fprintf(pFile, str); fclose(pFile); return TRUE; } #ifdef _UNICODE CStringA EncodingUnicodeToUTF8() { int nLength = m_str.GetLength(); CStringA saStr; WideCharToMultiByte(CP_UTF8, 0, m_str.GetBuffer(), nLength + 1, saStr.GetBuffer(nLength*3 + 1), nLength*3, NULL, NULL); saStr.ReleaseBuffer(); return saStr; } #else CString EncodingASCIIToUTF8() { int nLength = m_str.GetLength(); wchar_t* pWStr = new wchar_t[nLength + 1]; if (!pWStr) return _T(""); pWStr[nLength] = 0; MultiByteToWideChar(CP_ACP, 0, m_str, nLength, pWStr, nLength); int nLengthW = (int) wcslen(pWStr); CString cStr; WideCharToMultiByte(CP_UTF8, 0, pWStr, nLengthW + 1, cStr.GetBuffer(nLengthW*3 + 1), nLengthW*3, NULL, NULL); cStr.ReleaseBuffer(); delete[] pWStr; return cStr; } #endif void WriteString(const CString& strValue) { m_str += strValue; } void WriteInteger(int Value, int Base = 10) { char str[33]; _itoa(Value, str, Base); m_str += str; } void WriteDouble(double Value) { CString str; str.Format(_T("%lf"), Value); m_str += str; } void WriteBoolean(BOOL Value) { if (Value) m_str += _T("true"); else m_str += _T("false"); } void WriteNodeBegin(const CString& strNodeName, BOOL bAttributed = FALSE) { m_str += _T("<") + strNodeName; if (!bAttributed) m_str += _T(">"); } void WriteNodeEnd(const CString& strNodeName, BOOL bEmptyNode = FALSE, BOOL bEndNode = TRUE) { if (bEmptyNode) { if (bEndNode) m_str += _T(" />"); else m_str += _T(">"); } else m_str += _T(""); } void WriteNode(const CString& strNodeName, const CString& strNodeValue) { if (strNodeValue.GetLength() == 0) m_str += _T("<") + strNodeName + _T("/>"); else m_str += _T("<") + strNodeName + _T(">") + strNodeValue + _T(""); } void WriteNode(const CString& strNodeName, int nValue, int nBase = 10, const CString& strTextBeforeValue = _T(""), const CString& strTextAfterValue = _T("")) { WriteNodeBegin(strNodeName); WriteString(strTextBeforeValue); WriteInteger(nValue, nBase); WriteString(strTextAfterValue); WriteNodeEnd(strNodeName); } void WriteNode(const CString& strNodeName, double dValue) { WriteNodeBegin(strNodeName); WriteDouble(dValue); WriteNodeEnd(strNodeName); } void WriteAttribute(const CString& strAttributeName, const CString& strAttributeValue) { m_str += _T(" ") + strAttributeName + _T("=\"") + strAttributeValue + _T("\""); } void WriteAttribute(const CString& strAttributeName, int nValue, int nBase = 10, const CString& strTextBeforeValue = _T(""), const CString& strTextAfterValue = _T("")) { WriteString(_T(" ") + strAttributeName + _T("=")); WriteString(_T("\"")); WriteString(strTextBeforeValue); WriteInteger(nValue, nBase); WriteString(strTextAfterValue); WriteString(_T("\"")); } void WriteAttribute(const CString& strAttributeName, double dValue) { WriteString(_T(" ") + strAttributeName + _T("=")); WriteString(_T("\"")); WriteDouble(dValue); WriteString(_T("\"")); } }; class CXmlReader { CString m_str; XML::IXMLDOMDocument2Ptr m_pXmlDocument; XML::IXMLDOMNodeListPtr m_pXmlNodeList; protected: XML::IXMLDOMNodePtr m_pXmlNode; public: CXmlReader() { Clear(); m_pXmlDocument = NULL; if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument60)))) { if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument)))) { m_pXmlDocument = NULL; } } if (NULL != m_pXmlDocument) { m_pXmlDocument->setProperty( _bstr_t(_T("SelectionLanguage")), _variant_t(_T("XPath")) ); } } CXmlReader(BOOL bCreateDocument) { Clear(); m_pXmlDocument = NULL; if (bCreateDocument) { if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument60)))) { if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument)))) { m_pXmlDocument = NULL; } } if (NULL != m_pXmlDocument) { m_pXmlDocument->setProperty( _bstr_t(_T("SelectionLanguage")), _variant_t(_T("XPath")) ); } } } void Clear() { m_str.Empty(); m_pXmlNode = NULL; m_pXmlNodeList = NULL; } CString GetXmlString() { return m_str; } BOOL SetXmlString(const CString& strValue) { if (NULL == m_pXmlDocument) return FALSE; try { _bstr_t bstrXml; bstrXml = strValue; if (_T("") != strValue && VARIANT_TRUE == m_pXmlDocument->loadXML(bstrXml)) { if (ReadRootNode()) { m_str = strValue; return TRUE; } } } catch (...) { } Clear(); return FALSE; } void SetProperty(const CString& strName, const CString& strValue) { if (NULL != m_pXmlDocument) m_pXmlDocument->setProperty( _bstr_t((LPCTSTR)strName), _variant_t((LPCTSTR)strValue)); } BOOL OpenFromXmlString(const CString& strXml) { return SetXmlString(strXml); } BOOL OpenFromXmlNode(XML::IXMLDOMNodePtr& pXmlNode) { m_pXmlNode = pXmlNode; if (pXmlNode == NULL) return FALSE; return TRUE; } BOOL OpenFromFile(const CString& strFilePath) { if (NULL == m_pXmlDocument) return FALSE; BSTR bstrFilePath = strFilePath.AllocSysString(); BOOL bSuccess = FALSE; try { if (VARIANT_TRUE == m_pXmlDocument->load(bstrFilePath)) bSuccess = ReadRootNode(); } catch (...) { } if (!bSuccess) Clear(); SysFreeString(bstrFilePath); return bSuccess; } CString ReadNodeName() { if (NULL == m_pXmlNode) return _T(""); CString sName; try { BSTR bsName; m_pXmlNode->get_nodeName(&bsName); sName = bsName; SysFreeString(bsName); } catch (...) { } return sName; } BOOL ReadRootNode() { if (NULL == m_pXmlDocument) return FALSE; try { m_pXmlNode = m_pXmlDocument->firstChild; return TRUE; } catch (...) { } m_pXmlNode = NULL; m_pXmlNodeList = NULL; return FALSE; } BOOL ReadRootNode(const CString& strRootNodeName) { if (_T("") == strRootNodeName) return ReadRootNode(); if (NULL == m_pXmlDocument) return FALSE; try { _bstr_t bstrNode; bstrNode = strRootNodeName; m_pXmlNode = m_pXmlDocument->selectSingleNode(bstrNode); return TRUE; } catch (...) { } m_pXmlNode = NULL; m_pXmlNodeList = NULL; return FALSE; } BOOL ReadNode(const CString& strSubNodeName) { if (NULL == m_pXmlNode) return FALSE; try { _bstr_t bstrNode; bstrNode = strSubNodeName; XML::IXMLDOMElementPtr pNewNode = m_pXmlNode->selectSingleNode(bstrNode); if (NULL != pNewNode) { m_pXmlNode = pNewNode; return TRUE; } } catch (...) { } m_pXmlNode = NULL; return FALSE; } BOOL ReadChilds() { if (NULL == m_pXmlNode) return FALSE; try { XML::IXMLDOMNodeListPtr pNewNodeList = m_pXmlNode->GetchildNodes(); if (NULL != pNewNodeList) { m_pXmlNodeList = pNewNodeList; return TRUE; } } catch (...) { } m_pXmlNodeList = NULL; return FALSE; } BOOL ReadNodeList(const CString& strSubNodesName) { if (NULL == m_pXmlNode) return FALSE; try { _bstr_t bstrNodes; bstrNodes = strSubNodesName; XML::IXMLDOMNodeListPtr pNewNodeList = m_pXmlNode->selectNodes(bstrNodes); if (NULL != pNewNodeList) { m_pXmlNodeList = pNewNodeList; return TRUE; } } catch (...) { } m_pXmlNodeList = NULL; return FALSE; } CString ReadNodeAttributeOrValue(const CString& strSubNodeName, const CString& def = _T("")) { CString strAttributeValue = ReadNodeAttribute(strSubNodeName, strInvalidValue); if (strAttributeValue != strInvalidValue) return strAttributeValue; CString strNodeValue = ReadNodeValue(strSubNodeName, strInvalidValue); if (strNodeValue != strInvalidValue) return strNodeValue; return def; } CString ReadNodeValue(const CString& strSubNodeName, const CString& def = _T("")) { if (NULL == m_pXmlNode) return def; return GetNodeValue(m_pXmlNode, strSubNodeName, def); } CString ReadNodeAttribute(const CString& strAttributeName, const CString& def = _T("")) { if (NULL == m_pXmlNode) return def; return GetNodeAttrib(m_pXmlNode, strAttributeName, def); } CString ReadNodeText(const CString& def = _T("")) { if (NULL == m_pXmlNode) return def; return GetNodeText(m_pXmlNode, def); } CString ReadNodeXml(const CString& def = _T("")) { if (NULL == m_pXmlNode) return def; return GetNodeXml(m_pXmlNode, def); } BOOL ReadNodeTextTyped(_variant_t* variant, const CString& type = _T("bin.base64")) { if (NULL == m_pXmlNode) return FALSE; return GetNodeTextTyped(m_pXmlNode, variant, type); } CString ReadNodeName(int nIndex) { if (NULL == m_pXmlNodeList) return _T(""); CString sName; try { BSTR bsName; m_pXmlNodeList->item[nIndex]->get_nodeName(&bsName); sName = bsName; SysFreeString(bsName); } catch (...) { } return sName; } CString ReadNodeAttributeOrValue(int nIndex, const CString& strSubNodeName, const CString& def = _T("")) { CString strAttributeValue = ReadNodeAttribute(nIndex, strSubNodeName, strInvalidValue); if (strAttributeValue != strInvalidValue) return strAttributeValue; CString strNodeValue = ReadNodeValue(nIndex, strSubNodeName, strInvalidValue); if (strNodeValue != strInvalidValue) return strNodeValue; return def; } CString ReadNodeValue(int nIndex, const CString& strSubNodeName, const CString& def = _T("")) { if (NULL == m_pXmlNodeList) return def; return GetNodeValue(m_pXmlNodeList, nIndex, strSubNodeName, def); } CString ReadNodeAttribute(int nIndex, const CString& strAttributeName, const CString& def = _T("")) { if (NULL == m_pXmlNodeList) return def; return GetNodeAttrib(m_pXmlNodeList, nIndex, strAttributeName, def); } CString ReadNodeText(int nIndex, const CString& def = _T("")) { if (NULL == m_pXmlNodeList) return def; return GetNodeText(m_pXmlNodeList, nIndex, def); } CString ReadNodeXml(int nIndex, const CString& def = _T("")) { if (NULL == m_pXmlNodeList) return def; return GetNodeXml(m_pXmlNodeList, nIndex, def); } BOOL ReadNodeTextTyped(int nIndex, _variant_t* variant, const CString& type = _T("bin.base64")) { if (NULL == m_pXmlNodeList) return FALSE; return GetNodeTextTyped(m_pXmlNodeList, nIndex, variant, type); } int GetLengthList() { try { if (NULL == m_pXmlNodeList) return 0; int length = m_pXmlNodeList->length; return length; } catch (...) { } return 0; } BOOL GetNode(XML::IXMLDOMNodePtr& pXmlNode) { pXmlNode = m_pXmlNode; return (m_pXmlNode != NULL); } BOOL GetNode(int nIndex, XML::IXMLDOMNodePtr& pXmlNode) { if (m_pXmlNodeList == NULL) return FALSE; pXmlNode = m_pXmlNodeList->item[nIndex]; return TRUE; } }; }; namespace XmlUtils { static LPCTSTR g_cpszSADescriptorNodeName = _T("SADescriptor"); static LPCTSTR g_cpszSADimsAttributeName = _T("SADims"); static LPCTSTR g_cpszSASizeNodeNameFormat = _T("Size%d"); static LPCTSTR g_cpszSADataNodeName = _T("SAData"); static LPCTSTR g_cpszVariantTypeNodeAttr = _T("type"); struct SDispatchProperty { SDispatchProperty() : m_sName(_T("")) { } SDispatchProperty(const CString &sName, const VARIANT &var) : m_sName(sName) , m_varValue(var) { } CString m_sName; VARIANT m_varValue; }; class CDispatchPropertyList : public CAtlArray { public: CDispatchPropertyList() { } virtual ~CDispatchPropertyList() { size_t nCount = GetCount(); for (size_t nIndex = 0; nIndex < nCount; nIndex++) { if ((VT_BSTR==GetAt(nIndex).m_varValue.vt)&&(NULL!=GetAt(nIndex).m_varValue.bstrVal)) { SysFreeString(GetAt(nIndex).m_varValue.bstrVal); } else if ((0!=(VT_ARRAY & GetAt(nIndex).m_varValue.vt))&&(NULL!=GetAt(nIndex).m_varValue.parray)) SafeArrayDestroy(GetAt(nIndex).m_varValue.parray); } } }; static BOOL GetPropertyList(IDispatch *pDisp, CDispatchPropertyList &arProp, INVOKEKIND nType) { if (NULL==pDisp) return FALSE; ITypeInfo *pTypeInfo = NULL; pDisp->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &pTypeInfo); if (NULL==pTypeInfo) return FALSE; TYPEATTR* pTypeAttr = NULL; HRESULT hRes = pTypeInfo->GetTypeAttr(&pTypeAttr); if (S_OK!=hRes) { pTypeInfo->Release(); return FALSE; } int nMethodCount = pTypeAttr->cFuncs; for (int i=0; iGetFuncDesc(i, &pFuncDesc); if (S_OK!=hRes) continue; if (0!=pFuncDesc->cParams) continue; if (nType!=pFuncDesc->invkind) continue; BSTR bsName; unsigned int nCount; hRes = pTypeInfo->GetNames(pFuncDesc->memid, &bsName, 1, &nCount); if (S_OK!=hRes) continue; oPropRec.m_sName = bsName; SysFreeString(bsName); { DISPPARAMS dispParam; dispParam.cArgs = 0; dispParam.cNamedArgs = 0; dispParam.rgdispidNamedArgs = NULL; dispParam.rgvarg = NULL; hRes = pDisp->Invoke(pFuncDesc->memid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParam, &oPropRec.m_varValue, NULL, NULL); } pTypeInfo->ReleaseFuncDesc(pFuncDesc); arProp.Add(oPropRec); } pTypeInfo->ReleaseTypeAttr(pTypeAttr); pTypeInfo->Release(); return TRUE; } static BOOL ApplyPropertyList(IDispatch *pDisp, CDispatchPropertyList &arProp) { if (NULL==pDisp) return FALSE; long lCount = (long)arProp.GetCount(); for (long i=0; iGetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid); DISPPARAMS dispParam; DISPID dispidNamed = DISPID_PROPERTYPUT; dispParam.cArgs = 1; dispParam.cNamedArgs = 1; dispParam.rgdispidNamedArgs = &dispidNamed; dispParam.rgvarg = &arProp[i].m_varValue; HRESULT hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParam, NULL, NULL, NULL); } return TRUE; } class CDispatchXmlWriter : public CXmlWriter { public: CDispatchXmlWriter() { } ~CDispatchXmlWriter() { } void WriteNode(const CString& sName, const CLSID &clsid) { CStringW swGUID; int nSize = StringFromGUID2(clsid, swGUID.GetBuffer(50), 50); swGUID.ReleaseBuffer(nSize); CString sGUID; sGUID = swGUID; CXmlWriter::WriteNode(sName,sGUID); } void WriteNode(LPSAFEARRAY psa) { if (NULL==psa) return; UINT nDim = psa->cDims; if (0==nDim) return; ULONG ulSADataSize = 1; for (UINT nIndex = 0; nIndex < nDim; nIndex++) ulSADataSize *= psa->rgsabound[nIndex].cElements; if (0==ulSADataSize) return; CString sTemp; CXmlWriter::WriteNodeBegin(g_cpszSADescriptorNodeName, TRUE); CXmlWriter::WriteAttribute(g_cpszSADimsAttributeName, (int)nDim); CXmlWriter::WriteString(_T(">")); for (UINT nIndex = 0; nIndex < nDim; nIndex++) { sTemp.Format(g_cpszSASizeNodeNameFormat,nIndex); CXmlWriter::WriteNode(sTemp, (long)(psa->rgsabound[nIndex].cElements)); } CXmlWriter::WriteNodeEnd(g_cpszSADescriptorNodeName, FALSE); if (BinaryToBase64((LPBYTE)psa->pvData, ulSADataSize, sTemp)) CXmlWriter::WriteNode(g_cpszSADataNodeName, sTemp); else CXmlWriter::WriteNode(g_cpszSADataNodeName, _T("")); } void WriteNode(const CString &sName, const VARIANT &val) { if ((0!=(VT_VECTOR & val.vt)) || (0!=(VT_BYREF & val.vt))) return; if ((0!=(VT_ARRAY & val.vt))&&(VT_UI1 != (VT_TYPEMASK & val.vt))) return; CXmlWriter::WriteNodeBegin(sName, TRUE); CXmlWriter::WriteAttribute(g_cpszVariantTypeNodeAttr, val.vt); CXmlWriter::WriteString(_T(">")); if (0!=(VT_ARRAY & val.vt)) WriteNode(val.parray); else WriteString(VariantToString(val)); CXmlWriter::WriteNodeEnd(sName, FALSE); } void WritePropertyList(CDispatchPropertyList &arProp) { size_t nCount = arProp.GetCount(); for (size_t nIndex = 0; nIndexselectSingleNode(bstrNode); if (NULL==pNode) return 0; XML::IXMLDOMNodeListPtr pNodeList = pNode->selectNodes("*"); if (NULL != pNodeList) { long lNodeCount = pNodeList->length; CString sNodeName, sType, sValue; VARIANT val; for (long lIndex = 0; lIndexitem[lIndex]; sNodeName = ptrNode->baseName.GetBSTR(); sType = XmlUtils::GetNodeAttrib(ptrNode, g_cpszVariantTypeNodeAttr); sValue = ptrNode->text.GetBSTR(); val.vt = _ttoi(sType); if ((0!=(VT_VECTOR & val.vt)) || (0!=(VT_BYREF & val.vt))) continue; if (0!=(VT_ARRAY & val.vt)) { if (VT_UI1 != (VT_TYPEMASK & val.vt)) continue; if (!GetSafeArray(ptrNode, val.parray)) continue; } else { if (!GetVariantValue(sType, sValue, val)) continue; } arProp.Add(SDispatchProperty(sNodeName, val)); } } } catch (...) { } return (arProp.GetCount()); } protected: BOOL GetSafeArray(XML::IXMLDOMNodePtr ptrNode, LPSAFEARRAY &psa) { long lDims = 0; LPSAFEARRAYBOUND psabound = NULL; try { long lSize = 1; { _bstr_t bstrNode; bstrNode = g_cpszSADescriptorNodeName; XML::IXMLDOMElementPtr pDescriptionNode = ptrNode->selectSingleNode(bstrNode); CString sTemp = XmlUtils::GetNodeAttrib(pDescriptionNode, g_cpszSADimsAttributeName); lDims = _ttoi(sTemp); if (0==lDims) return FALSE; psabound = new SAFEARRAYBOUND[lDims]; if (NULL==psabound) return FALSE; for (long i=0; iselectSingleNode(bstrNode); CString sTemp; sTemp = pDataNode->text.GetBSTR(); if (!Base64ToBinary(sTemp, (LPBYTE)psa->pvData, lSize)) { delete []psabound; return FALSE; } } catch (...) { if (NULL != psabound) delete []psabound; return FALSE; } delete []psabound; return TRUE; } BOOL GetVariantValue(const CString &sType, const CString &sValue, VARIANT &val) { if ((sType.IsEmpty())||(sValue.IsEmpty())) return FALSE; val.vt = _ttoi(sType); BOOL bRet = TRUE; switch (VT_TYPEMASK & val.vt) { case VT_I2: val.iVal = _ttoi(sValue); break; case VT_I4: val.lVal = _ttoi(sValue); break; case VT_R4: val.fltVal = (float)_tstof(sValue); break; case VT_R8: val.dblVal = _tstof(sValue); break; case VT_DATE: val.date = _tstof(sValue); break; case VT_BSTR: val.bstrVal = sValue.AllocSysString(); break; case VT_BOOL: val.boolVal = (0!=_ttoi(sValue)) ? VARIANT_TRUE : VARIANT_FALSE; break; case VT_I1: val.cVal = _ttoi(sValue); break; case VT_UI1: val.bVal = _ttoi(sValue); break; case VT_UI2: val.uiVal = _ttoi(sValue); break; case VT_UI4: val.ulVal = _ttoi(sValue); break; case VT_I8: val.llVal = _ttoi(sValue); break; case VT_UI8: val.ullVal = _ttoi(sValue); break; case VT_INT: val.intVal = _ttoi(sValue); break; case VT_UINT: val.uintVal = _ttoi(sValue); break; case VT_DECIMAL: case VT_CY: case VT_EMPTY: case VT_NULL: case VT_SAFEARRAY: case VT_VOID: case VT_HRESULT: case VT_CARRAY: case VT_USERDEFINED: case VT_LPSTR: case VT_LPWSTR: case VT_RECORD: case VT_INT_PTR: case VT_UINT_PTR: case VT_FILETIME: case VT_BLOB: case VT_STREAM: case VT_STORAGE: case VT_STREAMED_OBJECT: case VT_STORED_OBJECT: case VT_BLOB_OBJECT: case VT_CF: case VT_CLSID: case VT_VERSIONED_STREAM: case VT_BSTR_BLOB: bRet = FALSE; break; } return bRet; } static BOOL Base64ToBinary(const CString& sData, BYTE* pData, int nSize) { if ((NULL==pData) || (0==nSize)) return FALSE; CStringA saData; saData = sData; return Base64Decode((LPCSTR)saData, saData.GetLength(), pData, &nSize); } }; }; namespace XmlUtils { AVSINLINE CString GetNamespace(CString& strNodeName) { int nFind = strNodeName.Find(TCHAR(':')); if (-1 == nFind) return _T(""); return strNodeName.Mid(0, nFind); } AVSINLINE CString GetNameNoNS(const CString& strNodeName) { int nFind = strNodeName.Find(TCHAR(':')); if (-1 == nFind) return strNodeName; return strNodeName.Mid(nFind + 1); } class IXmlNode { public: virtual BOOL FromXmlNode(XML::IXMLDOMNodePtr& pXmlNode) = 0; virtual BOOL FromXmlString(const CString& strXml) = 0; virtual BOOL FromXmlFile(const CString& strXmlFilePath, bool bRemoveRootNode = false) = 0; }; class CXmlNodes { XML::IXMLDOMNodeListPtr m_pXmlNodes; public: CXmlNodes() { Clear(); } void Clear() { m_pXmlNodes = NULL; } BOOL IsValid() { return (NULL != m_pXmlNodes); } BOOL FromXmlNodes(XML::IXMLDOMNodeListPtr& pXmlNodes) { try { Clear(); m_pXmlNodes = pXmlNodes; } catch (...) { Clear(); } return IsValid(); } int GetCount() { if (!IsValid()) return 0; return m_pXmlNodes->length; } BOOL GetAt(int nIndex, IXmlNode& oXmlNode) { if (nIndex < 0) return FALSE; try { XML::IXMLDOMNodePtr pXmlNode = NULL; pXmlNode = m_pXmlNodes->item[nIndex]; return oXmlNode.FromXmlNode(pXmlNode); } catch (...) { } return FALSE; } }; class CXmlNode : public IXmlNode { XML::IXMLDOMDocument2Ptr m_pXmlDocument; XML::IXMLDOMNodePtr m_pXmlNode; IXMLDOMNamedNodeMapPtr m_pAttributes; private: void CreateDocument() { if (NULL == m_pXmlDocument) { if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument30)))) { if (FAILED(m_pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument)))) { m_pXmlDocument = NULL; } } if (NULL != m_pXmlDocument) { m_pXmlDocument->put_preserveWhiteSpace(VARIANT_TRUE); } } } void ReadRootNode() { m_pXmlNode = m_pXmlDocument->firstChild; } public: void ReadRootNode(const CString& strRootNodeName) { if (strRootNodeName.IsEmpty()) return ReadRootNode(); _bstr_t bstrNode; bstrNode = strRootNodeName; m_pXmlNode = m_pXmlDocument->selectSingleNode(bstrNode); } template void ReadAllAttributes(T& strNames, T& strValues) { if (!IsValid()) return; if (NULL == m_pAttributes) { m_pAttributes = m_pXmlNode->attributes; if (NULL == m_pAttributes) return; } long lCountAttr = 0; m_pAttributes->get_length(&lCountAttr); for (long i = 0; i < lCountAttr; ++i) { IXMLDOMNodePtr tempNode; m_pAttributes->get_item(i, &tempNode); BSTR bsName; BSTR bsValue; tempNode->get_nodeName(&bsName); tempNode->get_text(&bsValue); strNames.AddTail((CString)bsName); strValues.AddTail((CString)bsValue); SysFreeString(bsName); SysFreeString(bsValue); } } public: CXmlNode() { Clear(); } void Clear() { m_pXmlDocument = NULL; m_pXmlNode = NULL; m_pAttributes = NULL; } inline BOOL IsValid() const { return (NULL != m_pXmlNode); } virtual BOOL FromXmlNode(XML::IXMLDOMNodePtr& pXmlNode) { try { Clear(); m_pXmlNode = pXmlNode; } catch (...) { Clear(); } return IsValid(); } virtual BOOL FromXmlString(const CString& strXml) { return FromXmlString(strXml, _T("")); } virtual BOOL FromXmlString(const CString& strXml, const CString& strNamespaces) { try { Clear(); CreateDocument(); if (_T("") != strNamespaces) { m_pXmlDocument->setProperty( _T("SelectionNamespaces"), _variant_t((LPCTSTR)strNamespaces)); } _bstr_t bstrXml; bstrXml = strXml; if (!strXml.IsEmpty() && VARIANT_TRUE == m_pXmlDocument->loadXML(bstrXml)) ReadRootNode(); } catch (...) { Clear(); } return IsValid(); } virtual BOOL FromXmlFile(const CString& strXmlFilePath, bool bRemoveRootNode = false) { BSTR bstrFilePath = strXmlFilePath.AllocSysString(); BOOL bSuccess = FALSE; try { Clear(); CreateDocument(); if ( bRemoveRootNode && VARIANT_TRUE == m_pXmlDocument->load(bstrFilePath)) { XML::IXMLDOMNodeListPtr ptrNodeList = m_pXmlDocument->childNodes; int nCount = ptrNodeList->length; for (int nIndex = 0; nIndex < nCount; nIndex++ ) { XML::IXMLDOMNodePtr ptrNode = ptrNodeList->item[nIndex]; int nType = ptrNode->nodeType; if (NODE_ELEMENT == nType) { m_pXmlNode = ptrNode; break; } } bSuccess = TRUE; } else { if (VARIANT_TRUE == m_pXmlDocument->load(bstrFilePath)) bSuccess = TRUE; ReadRootNode(); } } catch (...) { bSuccess = FALSE; } SysFreeString(bstrFilePath); if (!bSuccess) Clear(); return IsValid(); } virtual BOOL FromXmlFile2(const CString& strXmlFilePath) { BSTR bstrFilePath = strXmlFilePath.AllocSysString(); BOOL bSuccess = FALSE; try { Clear(); CreateDocument(); if (VARIANT_TRUE == m_pXmlDocument->load(bstrFilePath)) bSuccess = TRUE; m_pXmlNode = m_pXmlDocument->lastChild; } catch (...) { bSuccess = FALSE; } SysFreeString(bstrFilePath); if (!bSuccess) Clear(); return IsValid(); } CString GetName() { if (!IsValid()) return _T(""); CString strName; try { BSTR bstrName; m_pXmlNode->get_nodeName(&bstrName); strName = bstrName; SysFreeString(bstrName); } catch (...) { } return strName; } BSTR ReadAttributeBase(const _bstr_t& bstrName) { if (!IsValid()) return NULL; if (NULL == m_pAttributes) { m_pAttributes = m_pXmlNode->attributes; if (NULL == m_pAttributes) return NULL; } IXMLDOMNodePtr tempNode; m_pAttributes->getNamedItem(bstrName, &tempNode); if (NULL == tempNode) return NULL; BSTR strRes; tempNode->get_text(&strRes); return strRes; } template AVSINLINE void ReadAttributeBase(const _bstr_t& bsName, T& value) { BSTR bsVal = ReadAttributeBase(bsName); value = bsVal; SysFreeString(bsVal); } inline BSTR ReadAttribute(const CString& strAttibuteName) { _bstr_t bstrName = strAttibuteName; return ReadAttributeBase(bstrName); } BSTR ReadNodeTextBase(const _bstr_t& bsName) { if (!IsValid()) return NULL; try { XML::IXMLDOMNodePtr pNewNode = m_pXmlNode->selectSingleNode(bsName); if (NULL == pNewNode) return NULL; BSTR bsXml = NULL; pNewNode->get_text(&bsXml); return bsXml; } catch (...) { } return NULL; } template AVSINLINE void ReadNodeValueBase(const _bstr_t& bsName, T& value) { BSTR bsValue = ReadNodeTextBase(bsName); value = bsValue; SysFreeString(bsValue); } inline BSTR ReadNodeText(const CString& strName) { _bstr_t bsName = strName; return ReadNodeTextBase(bsName); } inline CString ReadValueString(const CString& sName, const CString& nDef = _T("")) { _bstr_t bsName = sName; BSTR bsRes = ReadNodeTextBase(bsName); if (NULL == bsRes) return nDef; CString str = (CString)bsRes; SysFreeString(bsRes); return str; } inline int ReadAttributeIntBase(const _bstr_t& bstrName, const int& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return nDef; int nRes = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); return nRes; } inline int ReadAttributeInt(const CString& str, const int& nDef = 0) { _bstr_t bsName = str; return ReadAttributeIntBase(bsName, nDef); } inline int ReadValueIntBase(const _bstr_t& bstrName, const int& nDef = 0) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return nDef; int nRes = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); return nRes; } inline int ReadValueInt(const CString& str, const int& nDef = 0) { _bstr_t bsName = str; return ReadValueIntBase(bsName, nDef); } inline void UpdateAttributeBase(const _bstr_t& bstrName, int& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateAttributeBase(const _bstr_t& bstrName, long& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return; nValue = (long)XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateAttribute(const CString& strName, int& nValue) { _bstr_t bsName = strName; return UpdateAttributeBase(bsName, nValue); } inline void UpdateAttribute(const CString& strName, long& nValue) { _bstr_t bsName = strName; return UpdateAttributeBase(bsName, nValue); } inline void UpdateValueBase(const _bstr_t& bstrName, int& nValue) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateValueBase(const _bstr_t& bstrName, long& nValue) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return; nValue = (long)XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateValue(const CString& strName, int& nValue) { _bstr_t bsName = strName; return UpdateValueBase(bsName, nValue); } inline void UpdateValue(const CString& strName, long& nValue) { _bstr_t bsName = strName; return UpdateValueBase(bsName, nValue); } inline int ReadAttributeOrValueIntBase(const _bstr_t& bstrName, const int& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return ReadValueIntBase(bstrName, nDef); int nRes = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); return nRes; } inline int ReadAttributeOrValueInt(const CString& strName, const int& nDef = 0) { _bstr_t bsName = strName; return ReadAttributeOrValueIntBase(bsName, nDef); } inline void UpdateAttributeOrValueBase(const _bstr_t& bstrName, int& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return UpdateValueBase(bstrName, nValue); nValue = XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateAttributeOrValueBase(const _bstr_t& bstrName, long& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return UpdateValueBase(bstrName, nValue); nValue = (long)XmlUtils::GetInteger(bsRes); SysFreeString(bsRes); } inline void UpdateAttributeOrValue(const CString& strName, int& nValue) { _bstr_t bsName = strName; return UpdateAttributeOrValueBase(bsName, nValue); } inline void UpdateAttributeOrValue(const CString& strName, long& nValue) { _bstr_t bsName = strName; return UpdateAttributeOrValueBase(bsName, nValue); } inline double ReadAttributeDoubleBase(const _bstr_t& bstrName, const double& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return nDef; double nRes = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); return nRes; } inline double ReadAttributeDouble(const CString& str, const double& nDef = 0) { _bstr_t bsName = str; return ReadAttributeDoubleBase(bsName, nDef); } inline double ReadValueDoubleBase(const _bstr_t& bstrName, const double& nDef = 0) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return nDef; double nRes = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); return nRes; } inline double ReadValueDouble(const CString& str, const double& nDef = 0) { _bstr_t bsName = str; return ReadValueDoubleBase(bsName, nDef); } inline void UpdateAttributeBase(const _bstr_t& bstrName, double& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); } inline void UpdateAttribute(const CString& strName, double& nValue) { _bstr_t bsName = strName; return UpdateAttributeBase(bsName, nValue); } inline void UpdateValueBase(const _bstr_t& bstrName, double& nValue) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); } inline void UpdateValue(const CString& strName, double& nValue) { _bstr_t bsName = strName; return UpdateValueBase(bsName, nValue); } inline double ReadAttributeOrValueDoubleBase(const _bstr_t& bstrName, const double& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return ReadValueDoubleBase(bstrName, nDef); double nRes = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); return nRes; } inline double ReadAttributeOrValueDouble(const CString& strName, const double& nDef = 0) { _bstr_t bsName = strName; return ReadAttributeOrValueDoubleBase(bsName, nDef); } inline void UpdateAttributeOrValueBase(const _bstr_t& bstrName, double& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return UpdateValueBase(bstrName, nValue); nValue = XmlUtils::GetDouble(bsRes); SysFreeString(bsRes); } inline void UpdateAttributeOrValue(const CString& strName, double& nValue) { _bstr_t bsName = strName; return UpdateAttributeOrValueBase(bsName, nValue); } inline float ReadAttributeFloatBase(const _bstr_t& bstrName, const float& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return nDef; float nRes = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); return nRes; } inline float ReadAttributeFloat(const CString& str, const float& nDef = 0) { _bstr_t bsName = str; return ReadAttributeFloatBase(bsName, nDef); } inline float ReadValueFloatBase(const _bstr_t& bstrName, const float& nDef = 0) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return nDef; float nRes = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); return nRes; } inline float ReadValueFloat(const CString& str, const float& nDef = 0) { _bstr_t bsName = str; return ReadValueFloatBase(bsName, nDef); } inline void UpdateAttributeBase(const _bstr_t& bstrName, float& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); } inline void UpdateAttribute(const CString& strName, float& nValue) { _bstr_t bsName = strName; return UpdateAttributeBase(bsName, nValue); } inline void UpdateValueBase(const _bstr_t& bstrName, float& nValue) { BSTR bsRes = ReadNodeTextBase(bstrName); if (NULL == bsRes) return; nValue = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); } inline void UpdateValue(const CString& strName, float& nValue) { _bstr_t bsName = strName; return UpdateValueBase(bsName, nValue); } inline float ReadAttributeOrValueFloatBase(const _bstr_t& bstrName, const float& nDef = 0) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return ReadValueFloatBase(bstrName, nDef); float nRes = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); return nRes; } inline float ReadAttributeOrValueFloat(const CString& strName, const float& nDef = 0) { _bstr_t bsName = strName; return ReadAttributeOrValueFloatBase(bsName, nDef); } inline void UpdateAttributeOrValueBase(const _bstr_t& bstrName, float& nValue) { BSTR bsRes = ReadAttributeBase(bstrName); if (NULL == bsRes) return UpdateValueBase(bstrName, nValue); nValue = XmlUtils::GetFloat(bsRes); SysFreeString(bsRes); } inline void UpdateAttributeOrValue(const CString& strName, float& nValue) { _bstr_t bsName = strName; return UpdateAttributeOrValueBase(bsName, nValue); } inline CString GetAttributeBase(const _bstr_t& strAttributeName, const CString& strDefaultValue = _T("")) { BSTR bsRes = ReadAttributeBase(strAttributeName); if (NULL == bsRes) return strDefaultValue; CString strRes = (CString)bsRes; SysFreeString(bsRes); return strRes; } inline CString GetAttribute(const CString& strAttributeName, const CString& strDefaultValue = _T("")) { _bstr_t bsName = strAttributeName; return GetAttributeBase(bsName, strDefaultValue); } inline CString GetAttributeNoSpace(const CString& strAttributeName, const CString& strDefaultValue = _T("")) { _bstr_t bsName = strAttributeName; BSTR bsRes = ReadAttributeBase(bsName); if (NULL == bsRes) return strDefaultValue; int nLen = SysStringLen(bsRes); if (0 == nLen) { SysFreeString(bsRes); return _T(""); } int nStart = 0; while (nStart < nLen) { if (bsRes[nStart] != WCHAR(' ')) break; ++nStart; } int nEnd = nLen - 1; while (nEnd > nStart) { if (bsRes[nEnd] != WCHAR(' ')) break; --nEnd; } if (nEnd < nStart) { SysFreeString(bsRes); return _T(""); } CString strRes(bsRes + nStart, nEnd - nStart + 1); SysFreeString(bsRes); return strRes; } inline CString GetValueBase(const _bstr_t& strAttributeName, const CString& strDefaultValue = _T("")) { BSTR bsRes = ReadNodeTextBase(strAttributeName); if (NULL == bsRes) return strDefaultValue; CString strRes = (CString)bsRes; SysFreeString(bsRes); return strRes; } inline CString GetValue(const CString& strAttributeName, const CString& strDefaultValue = _T("")) { _bstr_t bsName = strAttributeName; return GetValueBase(bsName); } inline void UpdateAttributeStringBase(const _bstr_t& strName, CString& strVal) { BSTR bsRes = ReadAttributeBase(strName); if (NULL == bsRes) return; strVal = (CString)bsRes; SysFreeString(bsRes); } inline void UpdateAttributeString(const CString& strName, CString& strVal) { _bstr_t bsName = strName; return UpdateAttributeStringBase(bsName, strVal); } inline void UpdateValueStringBase(const _bstr_t& strName, CString& strVal) { BSTR bsRes = ReadNodeTextBase(strName); if (NULL == bsRes) return; strVal = (CString)bsRes; SysFreeString(bsRes); } inline void UpdateValueString(const CString& strName, CString& strVal) { _bstr_t bsName = strName; return UpdateValueStringBase(bsName, strVal); } inline CString GetAttributeOrValueBase(const _bstr_t& strAttributeName, const CString& strDefaultValue = _T("")) { BSTR bsRes = ReadAttributeBase(strAttributeName); if (NULL == bsRes) return GetValueBase(strAttributeName, strDefaultValue); CString strRes = (CString)bsRes; SysFreeString(bsRes); return strRes; } inline CString GetAttributeOrValue(const CString& strAttributeName, const CString& strDefaultValue = _T("")) { _bstr_t bsName = strAttributeName; return GetAttributeOrValueBase(bsName, strDefaultValue); } inline void UpdateAttributeOrValueStringBase(const _bstr_t& strName, CString& strVal) { BSTR bsRes = ReadAttributeBase(strName); if (NULL == bsRes) return UpdateValueStringBase(strName, strVal); strVal = (CString)bsRes; SysFreeString(bsRes); } inline void UpdateAttributeOrValueString(const CString& strName, CString& strVal) { _bstr_t bsName = strName; return UpdateAttributeOrValueStringBase(bsName, strVal); } template AVSINLINE void LoadArray(const CString& sName, CAtlArray& arList) { XmlUtils::CXmlNodes oNodes; if (GetNodes(sName, oNodes)) { int nCount = oNodes.GetCount(); for (int i = 0; i < nCount; ++i) { XmlUtils::CXmlNode oItem; oNodes.GetAt(i, oItem); arList.Add(); arList[i].fromXML(oItem); } } } template AVSINLINE void LoadArray(const CString& sName, const CString& sSubName, CAtlArray& arList) { XmlUtils::CXmlNode oNode; if (GetNode(sName, oNode)) { XmlUtils::CXmlNodes oNodes; if (oNode.GetNodes(sSubName, oNodes)) { int nCount = oNodes.GetCount(); for (int i = 0; i < nCount; ++i) { XmlUtils::CXmlNode oItem; oNodes.GetAt(i, oItem); arList.Add(); arList[i].fromXML(oItem); } } } } AVSINLINE XmlUtils::CXmlNode ReadNode(const CString& strNodeName) { CXmlNode oNode; GetNode(strNodeName, oNode); return oNode; } AVSINLINE XmlUtils::CXmlNode ReadNodeNoNS(const CString& strNodeName) { XmlUtils::CXmlNodes oNodes; if (GetNodes(_T("*"), oNodes)) { int nCount = oNodes.GetCount(); for (int i = 0; i < nCount; ++i) { XmlUtils::CXmlNode node; oNodes.GetAt(i, node); if (strNodeName == GetNameNoNS(node.GetName())) return node; } } CXmlNode node; return node; } CString GetXml(const CString& strDefaultValue = _T("")) { if (!IsValid()) return strDefaultValue; return GetNodeXml(m_pXmlNode, strDefaultValue); } CString GetText(const CString& strDefaultValue = _T("")) { if (!IsValid()) return strDefaultValue; return GetNodeText(m_pXmlNode, strDefaultValue); } BOOL GetTextTyped(_variant_t* pVariant, const CString& strNodeType = _T("bin.base64")) { if (!IsValid()) return FALSE; return GetNodeTextTyped(m_pXmlNode, pVariant, strNodeType); } BOOL GetNode(const CString& strSubNodeName, CXmlNode& oXmlNode) { if (!IsValid()) return FALSE; try { _bstr_t bstrNode; bstrNode = strSubNodeName; XML::IXMLDOMNodePtr pNewNode = m_pXmlNode->selectSingleNode(bstrNode); if (NULL != pNewNode) return oXmlNode.FromXmlNode(pNewNode); } catch (...) { } return FALSE; } BOOL GetNodes(const CString& strSubNodesName, CXmlNodes& oXmlNodes) { if (!IsValid()) return FALSE; try { _bstr_t bstrNodes; bstrNodes = strSubNodesName; XML::IXMLDOMNodeListPtr pNewNodes = m_pXmlNode->selectNodes(bstrNodes); if (NULL != pNewNodes) return oXmlNodes.FromXmlNodes(pNewNodes); } catch (...) { } return FALSE; } BOOL GetChilds(CXmlNodes& oXmlNodes) { if (!IsValid()) return FALSE; try { XML::IXMLDOMNodeListPtr pNewNodeList = m_pXmlNode->GetchildNodes(); if (NULL != pNewNodeList) return oXmlNodes.FromXmlNodes(pNewNodeList); } catch (...) { } return FALSE; } CString GetTextExt(const CString& strDefaultValue = _T("")) { if (!IsValid()) return strDefaultValue; XML::IXMLDOMElementPtr run_elem = NULL; m_pXmlNode->QueryInterface(__uuidof(XML::IXMLDOMElement), (void**)&run_elem); run_elem->setAttribute(L"xml:space",(const _variant_t&)L"preserve"); return GetText(strDefaultValue); } CString GetTextExt2(const CString& strDefaultValue = _T("")) { if (!IsValid()) return strDefaultValue; return GetNodeValueExt(m_pXmlNode, strDefaultValue); } LONG GetTextLenExt() { if (!IsValid()) return 0; return (LONG)m_pXmlNode->xml.length(); } CString GetAttributeExt(const CString& strAttributeName, const CString& strDefaultValue = _T("")) { if (!IsValid()) return strDefaultValue; return GetNodeAttribExt(m_pXmlNode, strAttributeName, strDefaultValue); } CString GetAttributeOrValueExt(const CString& strSubNodeName, const CString& strDefaultValue = _T("")) { CString strAttributeValue = GetAttributeExt(strSubNodeName, strInvalidValue); if (strAttributeValue != strInvalidValue) return strAttributeValue; CXmlNode oNode; if (GetNode(strSubNodeName, oNode)) return oNode.GetTextExt(strDefaultValue); return strDefaultValue; } XML::IXMLDOMNamedNodeMapPtr GetAttributes() { if (NULL == m_pXmlNode) return NULL; return m_pXmlNode->attributes; } }; } namespace XmlUtils { static CStringW RemoveXMLRootNode (const CStringW& aXML) { CStringW sRes; try { XML::IXMLDOMDocument2Ptr pXmlDocument = NULL; if (FAILED(pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument60)))) { if (FAILED(pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument)))) { pXmlDocument = NULL; } } if (NULL != pXmlDocument) { pXmlDocument->setProperty( _bstr_t(_T("SelectionLanguage")), _variant_t(_T("XPath")) ); } _bstr_t bstrXml; bstrXml = aXML; if (VARIANT_TRUE == pXmlDocument->loadXML(bstrXml)) { XML::IXMLDOMNodeListPtr ptrNodeList = pXmlDocument->childNodes; for (int i = 0; i < ptrNodeList->length;) { XML::IXMLDOMNodePtr ptrNode = ptrNodeList->item[i]; if (NODE_ELEMENT == ptrNode->nodeType) break; pXmlDocument->removeChild(ptrNode); } sRes = pXmlDocument->xml.GetBSTR(); } } catch (...) { } return sRes; } static CStringA ConvertToUTF8 (const CStringW& aUnicodeXML) { CStringW sXML = RemoveXMLRootNode(aUnicodeXML); sXML.Insert(0, L""); int iSize = WideCharToMultiByte (CP_UTF8, 0, sXML, -1, NULL, 0, NULL, NULL); if (iSize <= 0) { ATLTRACE2 ("ConvertToUTF8() error (size detection): 0x%x\n", GetLastError()); return CStringA(sXML); } CStringA sOutXML; if (0 == WideCharToMultiByte (CP_UTF8, 0, sXML, -1, sOutXML.GetBuffer(iSize + 1), iSize, NULL, NULL)) { ATLTRACE2 ("ConvertToUTF8() error (utf-8 conversion): 0x%x\n", GetLastError()); return CStringA(sXML); } sOutXML.ReleaseBuffer(); return sOutXML; } static CStringW ConvertToUnicode (CStringA aAnsiUtf8XML) { CString sRootElement; sRootElement = aAnsiUtf8XML; int nXMLLength = sRootElement.GetLength(); int nStartPos (-1); int nEndPos (-1); CString sEncoding = _T("ascii"); try { if (nXMLLength > 7) { sRootElement.MakeLower(); nStartPos = sRootElement.Find(_T("= 0 && nStartPos < nXMLLength - 2) { nEndPos = sRootElement.Find(_T("?>"), nStartPos + 5); if (nEndPos > nStartPos && nEndPos < nXMLLength) { CString sXMLNode = sRootElement.Mid (nStartPos, nEndPos - nStartPos + 2); sXMLNode += _T(""); XML::IXMLDOMDocument2Ptr pXmlDocument = NULL; if (FAILED(pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument60)))) { if (FAILED(pXmlDocument.CreateInstance(__uuidof(MSXML::DOMDocument)))) { pXmlDocument = NULL; } } if (NULL != pXmlDocument) { pXmlDocument->setProperty( _bstr_t(_T("SelectionLanguage")), _variant_t(_T("XPath")) ); } _bstr_t bstrRootXml; bstrRootXml = sXMLNode; if (VARIANT_TRUE == pXmlDocument->loadXML(bstrRootXml)) { XML::IXMLDOMNodeListPtr ptrNodeList = pXmlDocument->childNodes; for (int i = 0; i < ptrNodeList->length; i++) { XML::IXMLDOMNodePtr ptrNode = ptrNodeList->item[i]; CString sName; sName = ptrNode->nodeName.GetBSTR(); sName.MakeLower(); if (_T("xml") == sName) { sEncoding = XmlUtils::GetNodeAttrib(ptrNode, _T("encoding"), _T("ascii")); break; } } } } } } } catch (...) { return CStringW (aAnsiUtf8XML); } sEncoding.MakeLower(); CStringW sw; if (_T("utf-8") == sEncoding) { int nSize = MultiByteToWideChar(CP_UTF8, 0, aAnsiUtf8XML.GetBuffer(), -1, NULL, 0); MultiByteToWideChar(CP_UTF8, 0, aAnsiUtf8XML.GetBuffer(), -1, sw.GetBuffer(nSize + 1), nSize); sw.ReleaseBuffer(); } else { int nSize = MultiByteToWideChar(CP_ACP, 0, aAnsiUtf8XML.GetBuffer(), -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, aAnsiUtf8XML.GetBuffer(), -1, sw.GetBuffer(nSize + 1), nSize); sw.ReleaseBuffer(); } return RemoveXMLRootNode(sw); } } class CWCharWrapper { public: CWCharWrapper():m_cwsString(NULL) { } CWCharWrapper(const wchar_t* cwsString):m_cwsString(cwsString) { } __forceinline const CWCharWrapper operator=(const wchar_t* cwsOther) { m_cwsString = cwsOther; return *this; } __forceinline const bool operator==(const wchar_t* cwsOther) { if ( 0 == WStrCmp( m_cwsString, cwsOther ) ) return true; return false; } __forceinline const bool operator!=(const wchar_t* cwsOther) { if ( 0 != WStrCmp( m_cwsString, cwsOther ) ) return true; return false; } __forceinline const wchar_t operator[](const int nIndex) const { int nLen = GetLength(); if ( nIndex >= nLen ) return '\0'; return m_cwsString[nIndex]; } __forceinline const bool IsNull() const { return (m_cwsString == NULL); } __forceinline const int GetLength() const { if ( NULL == m_cwsString ) return 0; return (const int)wcslen( m_cwsString ); } public: static __forceinline int WStrCmp(const wchar_t* cwsStr1, const wchar_t* cwsStr2) { if ( NULL == cwsStr1 && NULL == cwsStr2 ) return 0; else if ( NULL == cwsStr1 || NULL == cwsStr2 ) return -1; return wcscmp( cwsStr1, cwsStr2 ); } public: const wchar_t* m_cwsString; }; __forceinline const bool operator==(const wchar_t* cwsStr1, const CWCharWrapper& cwsStr2) { if ( 0 == CWCharWrapper::WStrCmp( cwsStr2.m_cwsString, cwsStr1 ) ) return true; return false; } __forceinline const bool operator!=(const wchar_t* cwsStr1, const CWCharWrapper& cwsStr2) { if ( 0 != CWCharWrapper::WStrCmp( cwsStr2.m_cwsString, cwsStr1 ) ) return true; return false; } #ifdef _USE_LIBXML2_READER_ #include "libxml2/libxml2.h" #else #ifdef _USE_XMLLITE_READER_ namespace XmlUtils { class CXmlLiteReader { public: CXmlLiteReader() { m_pReader = NULL; m_pStream = NULL; } ~CXmlLiteReader() { RELEASEINTERFACE( m_pReader ); RELEASEINTERFACE( m_pStream ); } public: inline void Clear() { RELEASEINTERFACE( m_pReader ); RELEASEINTERFACE( m_pStream ); } inline BOOL IsValid() { return ( NULL != m_pReader ); } inline BOOL FromFile(CString& sFilePath) { Clear(); if ( FAILED( ::SHCreateStreamOnFileW( sFilePath, STGM_READ, &m_pStream ) ) ) return FALSE; if ( FAILED( ::CreateXmlReader( __uuidof(IXmlReader), reinterpret_cast(&m_pReader), 0 ) ) ) { RELEASEINTERFACE( m_pStream ); return FALSE; } m_pReader->SetInput( m_pStream ); return TRUE; } inline BOOL FromString(CString& sXml) { Clear(); IStream *m_pStream = NULL; if ( FAILED( ::CreateStreamOnHGlobal( NULL, TRUE, &m_pStream ) ) ) return FALSE; ULONG cbWritten = 0; if ( FAILED( m_pStream->Write( (wchar_t*)sXml.GetBuffer(), sXml.GetLength() * sizeof(wchar_t), &cbWritten ) ) ) { RELEASEINTERFACE( m_pStream ); return FALSE; } LARGE_INTEGER liBeggining = { 0 }; if ( FAILED( m_pStream->Seek( liBeggining, STREAM_SEEK_SET, NULL ) ) ) { RELEASEINTERFACE( m_pStream ); return FALSE; } if ( FAILED( ::CreateXmlReader( __uuidof(IXmlReader), reinterpret_cast(&m_pReader), 0 ) ) ) { RELEASEINTERFACE( m_pStream ); return FALSE; } m_pReader->SetInput( m_pStream ); return TRUE; } inline BOOL Read(XmlNodeType &oNodeType) { if ( !IsValid() ) return FALSE; if ( FAILED( m_pReader->Read( &oNodeType ) ) ) return FALSE; return TRUE; } inline BOOL ReadNextNode() { if ( !IsValid() ) return FALSE; XmlNodeType oNodeType = XmlNodeType_None; while ( S_OK == m_pReader->Read( &oNodeType ) && XmlNodeType_Element != oNodeType ); if ( XmlNodeType_Element == oNodeType ) return TRUE; return FALSE; } inline BOOL ReadNextSiblingNode(int nDepth) { if ( !IsValid() ) return FALSE; XmlNodeType eNodeType = XmlNodeType_None; int nCurDepth = -1; while ( S_OK == m_pReader->Read( &eNodeType ) && (nCurDepth = GetDepth()) > nDepth ) { if ( XmlNodeType_Element == eNodeType && nCurDepth == nDepth + 1 ) return TRUE; else if ( XmlNodeType_EndElement == eNodeType && nCurDepth == nDepth + 1 ) return FALSE; } return FALSE; } inline BOOL ReadTillEnd(int nDepth = -2) { if ( !IsValid() ) return FALSE; if ( -2 == nDepth ) nDepth = GetDepth(); else if ( nDepth == GetDepth() && m_pReader->IsEmptyElement() ) return TRUE; XmlNodeType eNodeType = XmlNodeType_None; int nCurDepth = -1; while( TRUE ) { if ( S_OK != m_pReader->Read( &eNodeType ) ) break; nCurDepth = GetDepth(); if ( nCurDepth <= nDepth ) break; if ( XmlNodeType_EndElement == eNodeType && nCurDepth == nDepth + 1 ) break; } return TRUE; } inline const wchar_t* GetName() { if ( !IsValid() ) return NULL; const WCHAR* pwszQName; if ( FAILED( m_pReader->GetQualifiedName( &pwszQName, NULL ) ) ) return NULL; return pwszQName; } inline int GetDepth() { if ( !IsValid() ) return -1; UINT unDepth = 0; if ( S_OK != m_pReader->GetDepth( &unDepth ) ) return -1; return unDepth; } inline BOOL IsEmptyNode() { if ( !IsValid() ) return FALSE; return m_pReader->IsEmptyElement(); } inline const WCHAR *GetText() { if ( !IsValid() ) return NULL; const WCHAR* pwszValue; if ( FAILED( m_pReader->GetValue( &pwszValue, NULL ) ) ) return NULL; return pwszValue; } inline CString GetText2() { if ( !IsValid() ) return _T(""); CString sResult; if ( m_pReader->IsEmptyElement() ) return sResult; int nDepth = GetDepth(); XmlNodeType eNodeType = XmlNodeType_EndElement; while( Read( eNodeType ) && GetDepth() > nDepth && XmlNodeType_EndElement != eNodeType ) { if ( eNodeType == XmlNodeType_Text || eNodeType == XmlNodeType_Whitespace ) sResult += GetText(); } return sResult; } inline CString GetOuterXml() { return GetXml(false); } inline CString GetInnerXml() { return GetXml(true); } inline int GetAttributesCount() { if ( !IsValid() ) return -1; UINT unAttrsCount = 0; if ( FAILED( m_pReader->GetAttributeCount( &unAttrsCount ) ) ) return -1; return (int)unAttrsCount; } inline BOOL MoveToFirstAttribute() { if ( !IsValid() ) return FALSE; if ( S_OK != m_pReader->MoveToFirstAttribute() ) return FALSE; return TRUE; } inline BOOL MoveToNextAttribute() { if ( !IsValid() ) return FALSE; if ( S_OK != m_pReader->MoveToNextAttribute() ) return FALSE; return TRUE; } inline BOOL MoveToElement() { if ( !IsValid() ) return FALSE; if ( FAILED( m_pReader->MoveToElement() ) ) return FALSE; return TRUE; } private: inline CString GetXml(bool bInner) { if ( !IsValid() ) return _T(""); CStringWriter oResult; if(false == bInner) WriteElement(oResult); int nDepth = GetDepth(); if ( false == m_pReader->IsEmptyElement() ) { XmlNodeType eNodeType = XmlNodeType_None; int nCurDepth = -1; while( TRUE ) { if ( S_OK != m_pReader->Read( &eNodeType ) ) break; nCurDepth = GetDepth(); if ( eNodeType == XmlNodeType_Text || eNodeType == XmlNodeType_Whitespace ) oResult.WriteEncodeXmlString(GetText()); else if(eNodeType == XmlNodeType_Element) WriteElement(oResult); else if(eNodeType == XmlNodeType_EndElement) { if(false == bInner || nCurDepth != nDepth + 1) { oResult.AddChar2Safe(TCHAR('<'), TCHAR('/')); oResult.WriteEncodeXmlString(GetName()); oResult.AddCharSafe(TCHAR('>')); } } nCurDepth = GetDepth(); if ( nCurDepth <= nDepth ) break; if ( XmlNodeType_EndElement == eNodeType && nCurDepth == nDepth + 1 ) break; } } return oResult.GetData(); } void WriteElement(CStringWriter& oResult) { oResult.AddCharSafe((TCHAR)'<'); oResult.WriteEncodeXmlString(GetName()); if(GetAttributesCount() > 0) { MoveToFirstAttribute(); CString sName = GetName(); while( !sName.IsEmpty() ) { oResult.AddCharSafe(TCHAR(' ')); oResult.WriteEncodeXmlString(GetName()); oResult.AddChar2Safe(TCHAR('='), TCHAR('\"')); oResult.WriteEncodeXmlString(GetText()); oResult.AddCharSafe(TCHAR('\"')); if ( !MoveToNextAttribute() ) break; sName = GetName(); } MoveToElement(); } if (m_pReader->IsEmptyElement()) oResult.AddChar2Safe(TCHAR('/'), TCHAR('>')); else oResult.AddCharSafe(TCHAR('>')); } private: IStream *m_pStream; IXmlReader *m_pReader; }; enum EXmlLiteElement { xmlliteUnknown = 0, xmlliteNode = 1, xmlliteText = 2, xmlliteWhiteSpace = 3, }; struct TXmlLiteAttribute { TXmlLiteAttribute() { wsName = NULL; wsValue = NULL; } const TXmlLiteAttribute& operator=(const TXmlLiteAttribute& oOther) { wsName = oOther.wsName; wsValue = oOther.wsValue; return (*this); } wchar_t* wsName; wchar_t* wsValue; }; class CXmlLiteWrapper; class IXmlLiteElement { public: virtual ~IXmlLiteElement() {} virtual EXmlLiteElement get_Type() const = 0; }; class CXmlLiteText : public IXmlLiteElement { public: CXmlLiteText() { m_wsValue = NULL; } CXmlLiteText(const wchar_t* wsValue) { if ( NULL != wsValue ) m_wsValue = wcsdup( wsValue ); } virtual ~CXmlLiteText() { if ( m_wsValue ) free( m_wsValue ); } virtual EXmlLiteElement get_Type() const { return xmlliteText; } public: wchar_t* get_Text() const { return m_wsValue; } private: wchar_t* m_wsValue; }; class CXmlLiteWhiteSpace : public IXmlLiteElement { public: CXmlLiteWhiteSpace() { m_wsValue = NULL; } CXmlLiteWhiteSpace(const wchar_t* wsValue) { if ( NULL != wsValue ) m_wsValue = wcsdup( wsValue ); } virtual ~CXmlLiteWhiteSpace() { if ( m_wsValue ) free( m_wsValue ); } virtual EXmlLiteElement get_Type() const { return xmlliteWhiteSpace; } public: wchar_t* get_Text() const { return m_wsValue; } private: wchar_t* m_wsValue; }; class CXmlLiteNode : public IXmlLiteElement { public: CXmlLiteNode() { m_nIterator = 0; m_nAttrIterator = 0; m_wsName = NULL; } CXmlLiteNode(const wchar_t* wsName) { m_nIterator = 0; m_nAttrIterator = 0; if ( NULL != wsName ) m_wsName = wcsdup( wsName ); } virtual ~CXmlLiteNode() { if ( NULL != m_wsName ) free( m_wsName ); for ( int nIndex = 0; nIndex < m_arrAttributes.GetSize(); nIndex++ ) { if ( m_arrAttributes[nIndex].wsName ) free( m_arrAttributes[nIndex].wsName ); if ( m_arrAttributes[nIndex].wsValue ) free( m_arrAttributes[nIndex].wsValue ); } for ( int nIndex = 0; nIndex < m_arrChilds.GetSize(); nIndex++ ) { if ( m_arrChilds[nIndex] ) delete m_arrChilds[nIndex]; } } virtual EXmlLiteElement get_Type() const { return xmlliteNode; } public: wchar_t* get_Name() const { return m_wsName; } void move_ToStartNode() { m_nIterator = 0; } void move_ToFirstAttribute() { m_nAttrIterator = 0; } IXmlLiteElement* get_NextElement() { if ( m_nIterator >= m_arrChilds.GetSize() ) return NULL; return m_arrChilds[m_nIterator++]; } IXmlLiteElement* get_At(int nIndex) { if ( nIndex >= 0 && nIndex < m_arrChilds.GetSize() ) return m_arrChilds[nIndex]; return NULL; } TXmlLiteAttribute get_NextAttribute() { TXmlLiteAttribute oEmpty; if ( m_nAttrIterator >= m_arrAttributes.GetSize() ) return oEmpty; return m_arrAttributes[m_nAttrIterator++]; } wchar_t* get_Attribute(int nIndex) { if ( nIndex >= 0 && nIndex < m_arrAttributes.GetSize() ) return m_arrAttributes[nIndex].wsValue; return NULL; } wchar_t* get_Attribute(wchar_t* wsAttributeName) { for ( int nIndex = 0; nIndex < m_arrAttributes.GetSize(); nIndex++ ) { if ( 0 == CWCharWrapper::WStrCmp( wsAttributeName, m_arrAttributes[nIndex].wsName ) ) { return m_arrAttributes[nIndex].wsValue; } } return NULL; } TXmlLiteAttribute get_Attribute2(int nIndex) { TXmlLiteAttribute oEmpty; if ( nIndex >= 0 && nIndex < m_arrAttributes.GetSize() ) return m_arrAttributes[nIndex]; return oEmpty; } int get_AttributesCount() const { return m_arrAttributes.GetSize(); } CXmlLiteNode* get_NextNode() { IXmlLiteElement* pResult = NULL; while ( NULL != ( pResult = get_NextElement() ) ) { if ( xmlliteNode == pResult->get_Type() ) return ((CXmlLiteNode*)pResult); } return NULL; } protected: void add_Attribute(const wchar_t* wsName, const wchar_t* wsValue) { TXmlLiteAttribute oAttribute; if ( NULL != wsName ) oAttribute.wsName = wcsdup( wsName ); if ( NULL != wsValue ) oAttribute.wsValue = wcsdup( wsValue ); m_arrAttributes.Add( oAttribute ); } IXmlLiteElement* add_Child(const wchar_t* wsValue, EXmlLiteElement eType) { IXmlLiteElement* pChild = NULL; switch(eType) { case xmlliteNode: pChild = new CXmlLiteNode( wsValue ); break; case xmlliteText: pChild = new CXmlLiteText( wsValue ); break; case xmlliteWhiteSpace: pChild = new CXmlLiteWhiteSpace( wsValue ); break; } if ( NULL != pChild ) m_arrChilds.Add( pChild ); return pChild; } private: int m_nIterator; int m_nAttrIterator; wchar_t* m_wsName; CSimpleArray m_arrAttributes; CSimpleArray m_arrChilds; friend class CXmlLiteWrapper; }; class CXmlLiteWrapper : public CXmlLiteNode { public: virtual ~CXmlLiteWrapper() {} inline BOOL FromFile(CString& sFilePath) { CXmlLiteReader oReader; if ( !oReader.FromFile( sFilePath ) ) return FALSE; Parse( this, oReader ); return TRUE; } inline BOOL FromString(CString& sXml) { CXmlLiteReader oReader; if ( !oReader.FromString( sXml ) ) return FALSE; Parse( this, oReader ); return TRUE; } private: void Parse(CXmlLiteNode* pNode, CXmlLiteReader& oReader) { ParseAttributes( pNode, oReader ); int nCurDepth = oReader.GetDepth(); if ( oReader.IsEmptyNode() ) return; XmlNodeType eNodeType; while ( oReader.Read( eNodeType ) && ( oReader.GetDepth() > nCurDepth + 1 || XmlNodeType_EndElement != eNodeType ) && XmlNodeType_None != eNodeType ) { switch( eNodeType ) { case XmlNodeType_Text: pNode->add_Child( oReader.GetText(), xmlliteText ); break; case XmlNodeType_Whitespace: pNode->add_Child( oReader.GetText(), xmlliteWhiteSpace ); break; case XmlNodeType_Element: { CXmlLiteNode* pNewNode = (CXmlLiteNode*)pNode->add_Child( oReader.GetName(), xmlliteNode ); if ( NULL != pNewNode ) Parse( pNewNode, oReader ); break; } } } } void ParseAttributes(CXmlLiteNode* pNode, CXmlLiteReader& oReader) { if ( oReader.GetAttributesCount() <= 0 ) return; if ( !oReader.MoveToFirstAttribute() ) return; const wchar_t* wsName = oReader.GetName(); while( NULL != wsName ) { const wchar_t* wsValue = oReader.GetText(); pNode->add_Attribute( wsName, wsValue ); if ( !oReader.MoveToNextAttribute() ) break; wsName = oReader.GetName(); } oReader.MoveToElement(); } }; } #endif #endif