Listing 2: xmlif.cpp Implementation of CXmlIF
/*** * MODULE: XmlIF.cpp * PURPOSE: Implementation...XML Interface Class * AUTHOR: Ben Campione ***/ #include "stdafx.h" #include "XmlIF.h" // Initialize XML Interface Object bool CXmlIF::Initialize(void) { // Initialize Members ClearParseError(); m_szURL[0] = 0; m_bInitialized = FALSE; m_bLoaded = FALSE; m_pDoc = NULL; m_pDocNode = NULL; // Initialize COM Library if (CoInitialize(NULL) == S_OK) { // Create An Empty XML Document m_hr = CoCreateInstance(MS_XML_NS::CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, MS_XML_NS::IID_IXMLDOMDocument, (void**) &m_pDoc); m_bInitialized = (m_hr == S_OK) ? TRUE : FALSE; if (m_bInitialized) m_pDoc->put_async(VARIANT_FALSE); } return m_bInitialized; } // UnInitialize XML Interface Object void CXmlIF::UnInitialize(void) { // Cleanup Allocated Memory if (m_pDocNode) m_pDocNode->Release(); if (m_pDoc) m_pDoc->Release(); // Uninitialize COM Library CoUninitialize(); // Initialize Members ClearParseError(); m_szURL[0] = 0; m_bInitialized = FALSE; m_bLoaded = FALSE; m_pDocNode = NULL; m_pDoc = NULL; } // Convert ascii string to BSTR BSTR CXmlIF::AsciiToBSTR(const char* pszString) { WCHAR wszURL[XIF_MAX_STRING+1]; ::MultiByteToWideChar(CP_ACP, 0, pszString, -1, wszURL, XIF_MAX_STRING); return (::SysAllocString(wszURL)); } // Convert ascii string to BSTR char* CXmlIF::BSTRToAscii(const BSTR pwszString) { char* pszURL = new char[XIF_MAX_STRING+1]; ::WideCharToMultiByte(CP_ACP, 0, pwszString, -1, pszURL, XIF_MAX_STRING, NULL, NULL); return pszURL; } // Get XML File Parsing Error Information void CXmlIF::GetParseError(MS_XML_NS::IXMLDOMParseError *pXMLError) { if (pXMLError) { BSTR pBReason; pXMLError->get_reason(&pBReason); pXMLError->get_line(&m_lErrLine); pXMLError->get_linepos(&m_lErrPos); char* pszReason = BSTRToAscii(pBReason); strncpy(m_szErrReason, pszReason, XIF_MAX_STRING); ::SysFreeString(pBReason); delete pszReason; } } // Clear XML File Parsing Error Information void CXmlIF::ClearParseError(void) { m_szErrReason[0] = 0; m_lErrLine = -1; m_lErrPos = -1; } // Check Document Load Results HRESULT CXmlIF::CheckLoad(MS_XML_NS::IXMLDOMDocument* pDoc) { // Since We Don't Have The VARIANT_BOOL From LoadDocument(), // Check The Parse Error Property (errorCode) To Validate LONG errorCode = E_FAIL; MS_XML_NS::IXMLDOMParseError *pXMLError = NULL; if (pDoc->get_parseError(&pXMLError) == S_OK) { if (pXMLError->get_errorCode(&errorCode) == S_OK) { if (errorCode != 0) GetParseError(pXMLError); else ClearParseError(); } } pXMLError->Release(); return errorCode; } // Load XML Document From Specified URL bool CXmlIF::LoadDocument(const char* szURL) { // Must Be Initialized Prior To Loading Document if (!m_bInitialized || !szURL) return FALSE; // Convert File Name To BSTR strncpy(m_szURL, szURL, _MAX_PATH); BSTR pBURL = AsciiToBSTR(m_szURL); // Setup Variant URL For Load Method VARIANT vURL; VariantInit(&vURL); vURL.vt = VT_BSTR; V_BSTR(&vURL) = pBURL; // Load Xml Document From Specified URL m_bLoaded = FALSE; VARIANT_BOOL vb; if ((m_hr=GetDocument()->XML_LOAD(vURL, &vb)) == S_OK) { if (!CheckLoad(GetDocument())) m_bLoaded = TRUE; } // Set Member Document And Current Node To Top Level Node SetDocumentNode(); ::SysFreeString(pBURL); return m_bLoaded; } // Save XML Document To Specified URL bool CXmlIF::SaveDocument(const char* szURL) { if (!m_bInitialized || !szURL) return FALSE; // Convert Argument to Variant BSTR pBURL = AsciiToBSTR(szURL); VARIANT vURL; VariantInit(&vURL); vURL.vt = VT_BSTR; V_BSTR(&vURL) = pBURL; // Save Xml Document To Specified URL bool bFlag = (GetDocument()->save(vURL) == S_OK) ? TRUE : FALSE; ::SysFreeString(pBURL); return bFlag; } // Set Top Level Document Node bool CXmlIF::SetDocumentNode(void) { if (!m_bInitialized) return FALSE; bool bFlag = FALSE; if (SUCCEEDED(m_pDoc->QueryInterface(MS_XML_NS::IID_IXMLDOMNode, (void**) &m_pDocNode))) bFlag = TRUE; return bFlag; } // Insert Processing Instruction Node Into Document. // Must Be Executed Prior To Creating Any Other Nodes bool CXmlIF::InsertProcessingInst(void) { if (!m_bInitialized) return FALSE; bool bFlag = FALSE; MS_XML_NS::IXMLDOMProcessingInstruction* pPI = NULL; BSTR pBTarget = (L"xml"); BSTR pBData = (L" version=\"1.0\""); if (SUCCEEDED(m_pDoc->XML_CRP(pBTarget, pBData, &pPI))) m_pDoc->XML_APPCHILD(pPI, NULL); return bFlag; } // Get Name From This Node bool CXmlIF::GetName(MS_XML_NS::IXMLDOMNode* pNode, BSTR pBName, UINT uSize) { if (!pNode || !pBName || uSize <= 0) return FALSE; BSTR pBNodeName = NULL; bool bFlag = (pNode->get_nodeName(&pBNodeName) == S_OK) ? TRUE : FALSE; if (bFlag) { wcsncpy(pBName, pBNodeName, uSize); ::SysFreeString(pBNodeName); } return bFlag; } // Set Node Text To Argument Value bool CXmlIF::SetText(MS_XML_NS::IXMLDOMNode* pNode, BSTR pBText) { if (!pNode || !pBText) return FALSE; return ((pNode->put_text(pBText) == S_OK) ? TRUE : FALSE); } // Get Specified Text From This Node bool CXmlIF::GetText(MS_XML_NS::IXMLDOMNode* pNode, BSTR pBText, UINT uSize) { if (!pNode || !pBText || uSize <= 0) return FALSE; BSTR pBNodeText = NULL; bool bFlag = (pNode->get_text(&pBNodeText) == S_OK) ? TRUE : FALSE; if (bFlag) { wcsncpy(pBText, pBNodeText, uSize); ::SysFreeString(pBNodeText); } return bFlag; } // Set Node Value To Argument Value bool CXmlIF::SetValue(MS_XML_NS::IXMLDOMNode* pNode, BSTR pBValue) { if (!pNode || !pBValue) return FALSE; // Set Value As Variant Type VARIANT vValue; VariantInit(&vValue); vValue.vt = VT_BSTR; V_BSTR(&vValue) = pBValue; return ((pNode->put_nodeValue(vValue) == S_OK) ? TRUE : FALSE); } // Get Specified Value From This Node bool CXmlIF::GetValue(MS_XML_NS::IXMLDOMNode* pNode, BSTR pBValue, UINT uSize) { if (!pNode || !pBValue || uSize <= 0) return FALSE; VARIANT vValue; VariantInit(&vValue); bool bFlag = (pNode->get_nodeValue(&vValue) == S_OK) ? TRUE : FALSE; if (vValue.vt == VT_BSTR) wcsncpy(pBValue, V_BSTR(&vValue), uSize); return bFlag; } // Get List Of All Child Nodes MS_XML_NS::IXMLDOMNodeList* CXmlIF::GetChildren(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, long* pCnt) { if (!pNode) return NULL; // Get List Of All Children, Either Name Matched Or All Children MS_XML_NS::IXMLDOMNodeList* pList = NULL; if (!pBName) pNode->get_childNodes(&pList); else pNode->XML_SELNODES(pBName, &pList); // Get Number Of Items In List...If NULL, Don't Fill Arguement if (pCnt) { if (pList) pList->get_length(pCnt); else *pCnt = 0; } return pList; // NOTE: Calling Method Must Call pList->Release() } // Get Indexed Child From Argument List...Index Is Zero Based MS_XML_NS::IXMLDOMNode* CXmlIF::GetChild(MS_XML_NS::IXMLDOMNodeList* pList, const long lItem) { if (!pList) return NULL; // Sanity Check long lListCnt = 0; pList->get_length(&lListCnt); if (lItem >= lListCnt) return NULL; // Get Node List Item That Matches The Occurance MS_XML_NS::IXMLDOMNode* pChild = NULL; pList->get_item(lItem, &pChild); return pChild; // NOTE: Calling Method Must Call pChild->Release() } // Get Child From Node Using Element Name For Pattern Matching MS_XML_NS::IXMLDOMNode* CXmlIF::GetChild(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, UINT uOccurance) { if (!pNode || !pBName) return NULL; // Get List Of Matching Child Nodes long lListCnt = 0; MS_XML_NS::IXMLDOMNodeList* pList = GetChildren(pNode, pBName, &lListCnt); // Set Which Occurance Of Element Name To Return...Occurance Is One Based long lItem = (lListCnt < (long) uOccurance) ? lListCnt : (long) uOccurance; if (lItem > 0) lItem--; else lItem = 0; // Get Node List Item That Matches The Occurance MS_XML_NS::IXMLDOMNode* pChild = NULL; if (pList) { pList->get_item(lItem, &pChild); pList->Release(); } return pChild; // NOTE: Calling Method Must Call pChild->Release() } // Create Child Under Argument Node And Append To Child Map MS_XML_NS::IXMLDOMNode* CXmlIF::CreateChild(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, int nType) { if (!m_bInitialized || !pNode || !pBName) return NULL; // Set Node Type As Variant VARIANT vType; vType.vt = VT_I4; V_I4(&vType) = nType; // Create New Node MS_XML_NS::IXMLDOMNode* pChild = NULL; if (SUCCEEDED(m_pDoc->XML_CRTNODE(vType, pBName, (L""), &pChild))) pNode->XML_APPCHILD(pChild, NULL); return pChild; // NOTE: Calling Method Must Call pChild->Release() } // Get Specified Attribute From This Node Using Attribute Name MS_XML_NS::IXMLDOMNamedNodeMap* CXmlIF::GetAttributeList( MS_XML_NS::IXMLDOMNode* pNode, long* pCnt) { if (!pNode) return NULL; // Get All Node Attributes MS_XML_NS::IXMLDOMNamedNodeMap* pAttrs = NULL; MS_XML_NS::IXMLDOMNode* pChild = NULL; pNode->get_attributes(&pAttrs); // Get Number Of Items In List...If NULL, Don't Fill Arguement if (pCnt) { if (pAttrs) pAttrs->get_length(pCnt); else *pCnt = 0; } return pAttrs; // NOTE: Calling Method Must Call pAttrs->Release() } // Get Indexed Attribute From Argument List...Index Is Zero Based MS_XML_NS::IXMLDOMNode* CXmlIF::GetAttribute( MS_XML_NS::IXMLDOMNamedNodeMap* pAttrs, long lIndex) { if (!pAttrs) return NULL; MS_XML_NS::IXMLDOMNode* pAttr = NULL; pAttrs->get_item(lIndex, &pAttr); return pAttr; // NOTE: Calling Method Must Call pAttr->Release() } // Get Attribute From Node Using Attribute Name For Pattern Matching MS_XML_NS::IXMLDOMNode* CXmlIF::GetAttribute(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName) { if (!pNode || !pBName) return NULL; // Get All Node Attributes MS_XML_NS::IXMLDOMNamedNodeMap* pAttrs = NULL; MS_XML_NS::IXMLDOMNode* pAttr = NULL; if (SUCCEEDED(pNode->get_attributes(&pAttrs)) && pAttrs != NULL) { // Get Specific Attribute Using Name For Tag Lookup pAttrs->XML_GETNI(pBName, &pAttr); pAttrs->Release(); } return pAttr; // NOTE: Calling Method Must Call pAttr->Release() } // Create Specified Attribute From This Node Using Attribute Name MS_XML_NS::IXMLDOMAttribute* CXmlIF::CreateAttribute( MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, const BSTR pBValue) { if (!m_bInitialized || !pNode || !pBName || !pBValue) return NULL; // Convert BSTR To Variant Type VARIANT vValue; VariantInit(&vValue); vValue.vt = VT_BSTR; V_BSTR(&vValue) = pBValue; // Create New Node Attribute And Set Value MS_XML_NS::IXMLDOMAttribute* pNewAttr = NULL; m_pDoc->XML_CRTATTR(pBName, &pNewAttr); pNewAttr->put_value(vValue); // Append New Attribute To This Nodes List AppendAttribute(pNode, pNewAttr); return pNewAttr; // NOTE: Calling Method Must Call pNewAttr->Release() } // Create Specified Attribute From This Node Using Attribute Name void CXmlIF::AppendAttribute(MS_XML_NS::IXMLDOMNode* pNode, MS_XML_NS::IXMLDOMAttribute* pAttr) { if (!pNode || !pAttr) return; MS_XML_NS::IXMLDOMNamedNodeMap* pAttrs = NULL; if (SUCCEEDED(pNode->get_attributes(&pAttrs)) && pAttrs != NULL) { pAttrs->XML_SETNI(pAttr, NULL); pAttrs->Release(); } } // Set Attribute Value To Arguement Value bool CXmlIF::SetAttributeValue(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, BSTR pBValue) { if (!pNode || !pBName || !pBValue) return FALSE; // Get Node Attribute And Set Value bool bFlag = FALSE; MS_XML_NS::IXMLDOMNode* pChild = GetAttribute(pNode, pBName); if (pChild) { bFlag = SetValue(pChild, pBValue); pChild->Release(); } return bFlag; } // Get Specified Attribute Value From This Node Using Attribute Name bool CXmlIF::GetAttributeValue(MS_XML_NS::IXMLDOMNode* pNode, const BSTR pBName, BSTR pBValue, UINT uSize) { if (!pNode || !pBName || !pBValue || uSize <= 0) return FALSE; // Get Node Attribute Value bool bFlag = FALSE; MS_XML_NS::IXMLDOMNode* pChild = GetAttribute(pNode, pBName); if (pChild) { bFlag = GetValue(pChild, pBValue, uSize); pChild->Release(); } return bFlag; } //End of File