BOOL CKADmerge::HasNode(IXMLDOMNode * pXMLNode, string sPatternString, IXMLDOMNode ** pXMLTarget) { BOOL bRet = FALSE; HRESULT hRes = 0; LONG lListLength = 0; IXMLDOMNodeList * pXMLNodeList = NULL; _bstr_t bPatternString(sPatternString.c_str()); hRes = pXMLNode->selectNodes(bPatternString, &pXMLNodeList); if(SUCCEEDED(hRes)) { hRes = pXMLNodeList->get_length(&lListLength); if(lListLength) { hRes = pXMLNodeList->nextNode(pXMLTarget); bRet = TRUE; } else { string str01 = GetName(pXMLNode); string str02 = GetName(*pXMLTarget); bRet = FALSE; } } if(pXMLNodeList) pXMLNodeList->Release(); return bRet; }
// FindElements UINT COpcXmlDocument::FindElements(const COpcString& cXPath, COpcXmlElementList& cElements) { cElements.RemoveAll(); // check if document exists. if (m_ipDocument == NULL) { return 0; } // search for matching nodes. IXMLDOMNodeList* ipNodes = NULL; BSTR bstrQuery = SysAllocString(cXPath); HRESULT hResult = m_ipDocument->selectNodes(bstrQuery, &ipNodes); SysFreeString(bstrQuery); if (FAILED(hResult)) { return 0; } // add found nodes to element list. do { IXMLDOMNode* ipNode = NULL; hResult = ipNodes->nextNode(&ipNode); if (hResult != S_OK || ipNode == NULL) { break; } COpcXmlElement cElement(ipNode); ipNode->Release(); if (cElement != NULL) { cElements.Append(cElement); } } while (SUCCEEDED(hResult)); if (ipNodes != NULL) { ipNodes->Release(); } // return the number of elements found. return cElements.GetSize(); }
/* Function name : CXML::GetRootNode Description : This helper function retrieves the DOM pointer to the root node Return type : bool Argument : CString csRootTagName Tested : Ok */ bool CXML::GetRootNode(CString csRootTagName) { IXMLDOMNodeList * pINodeList = NULL; _bstr_t bstrRootTagName(csRootTagName); m_hr = m_pXMLDoc->getElementsByTagName(bstrRootTagName ,&pINodeList); if(!SUCCEEDED(m_hr)) return false; m_hr = pINodeList->nextNode(&m_pIRootNode); pINodeList->Release(); if(!SUCCEEDED(m_hr)) return false; return true; }
IXMLDOMNode *CXML::NextChildNode(IXMLDOMNode **ppNode) { if(!(*ppNode)) return NULL; IXMLDOMNode * pNode = NULL; IXMLDOMNodeList * pChildList = NULL; // Get the list of child nodes of the current node m_hr = (*ppNode)->get_childNodes(&pChildList); if (!SUCCEEDED(m_hr)) return NULL; // loop through the childs DOMNodeType nodeType; while(true) { // Get the node type of each child, if it is of NODE_ELEMENT type set it as current node m_hr = pChildList->nextNode(&pNode); if(!SUCCEEDED(m_hr)) { pChildList->Release(); return NULL; } if(!pNode) break; m_hr = pNode->get_nodeType(&nodeType); if(!SUCCEEDED(m_hr)) { pChildList->Release(); pNode->Release(); return NULL; } if(nodeType == NODE_ELEMENT) break; if(pNode) pNode->Release(); } if(pChildList) pChildList->Release(); return pNode; }
/* Function name : CXML::ReplaceNodeText Description : This Helper function replaces the existing text with the given text of : the given node. Return type : bool Argument : IXMLDOMNode **pNode Argument : CString &rcsNodeText Tested : */ bool CXML::ReplaceNodeText(IXMLDOMNode **pNode,CString &rcsNodeText) { IXMLDOMText * pTextNode = NULL; if(!(*pNode)) return false; IXMLDOMNode * pTempNode = NULL; DOMNodeType nodeType; IXMLDOMNode * pINewNode = NULL; IXMLDOMNode * pIOldNode = NULL; IXMLDOMNodeList * pChildList = NULL; long nLen = 0,i=0; _bstr_t bstrData(rcsNodeText); m_hr = m_pXMLDoc->createTextNode(bstrData,&pTextNode); if(!SUCCEEDED(m_hr) || !pTextNode) goto on_Error; m_hr = (*pNode)->get_childNodes(&pChildList); if(!SUCCEEDED(m_hr) || !pChildList) goto on_Error; m_hr = pChildList->get_length(&nLen); if(!SUCCEEDED(m_hr)) goto on_Error; if(nLen == 0) // no childs, if the tag is empty { bool bRet = CreateNodeText(pNode,rcsNodeText); if(pChildList) pChildList->Release(); if(pTextNode) pTextNode->Release(); return bRet; } for(i =0; i< nLen;++i) { m_hr = pChildList->nextNode(&pTempNode); if(!SUCCEEDED(m_hr)) goto on_Error; m_hr = pTempNode->get_nodeType(&nodeType); if(!SUCCEEDED(m_hr)) goto on_Error; if(nodeType == NODE_TEXT) break; if(pTempNode) { pTempNode->Release(); pTempNode = NULL; } } m_hr = (*pNode)->replaceChild(pTextNode,pTempNode,&pINewNode); if(!SUCCEEDED(m_hr) || !pINewNode) goto on_Error; if(pChildList) pChildList->Release(); if(pTextNode) pTextNode->Release(); if(pINewNode) pINewNode->Release(); if(pTempNode) pTempNode->Release(); return true; on_Error: // Release all the References if(pChildList) pChildList->Release(); if(pTextNode) pTextNode->Release(); if(pINewNode) pINewNode->Release(); if(pTempNode) pTempNode->Release(); return false; }
bool CXML::NextChildNode() { if(!m_pICurrentNode) return false; IXMLDOMNode * pNode = NULL; IXMLDOMNode * pITempNode = m_pICurrentNode; pITempNode->AddRef(); IXMLDOMNodeList * pChildList = NULL; // Get the list of child nodes of the current node m_hr = pITempNode->get_childNodes(&pChildList); pITempNode->Release(); if (!SUCCEEDED(m_hr)) return false; // loop through the childs DOMNodeType nodeType; while(true) { // Get the node type of each child, if it is of NODE_ELEMENT type set it as current node m_hr = pChildList->nextNode(&pNode); if(!SUCCEEDED(m_hr)) { pChildList->Release(); return false; } if(!pNode) break; m_hr = pNode->get_nodeType(&nodeType); if(!SUCCEEDED(m_hr)) { pChildList->Release(); pNode->Release(); return false; } if(nodeType == NODE_ELEMENT) break; if(pNode) pNode->Release(); } if(pChildList) pChildList->Release(); if(pNode) { if(m_pICurrentNode) { m_pICurrentNode->Release(); m_pICurrentNode = NULL; } m_pICurrentNode = pNode; m_pICurrentNode->AddRef(); pNode->Release(); return true; } return false; }
// эта функция, если значения нет (или тип некорректный) *value НЕ трогает bool SettingsXML::Load(const wchar_t *regName, wchar_t **value) { bool lbRc = false; HRESULT hr = S_OK; IXMLDOMNode* pChild = NULL; IXMLDOMNamedNodeMap* pAttrs = NULL; IXMLDOMAttribute *pIXMLDOMAttribute = NULL; IXMLDOMNode *pNode = NULL; IXMLDOMNodeList* pList = NULL; BSTR bsType = NULL; BSTR bsData = NULL; size_t nLen = 0; //if (*value) {free(*value); *value = NULL;} if (mp_Key) pChild = FindItem(mp_Key, L"value", regName, false); if (!pChild) return false; hr = pChild->get_attributes(&pAttrs); if (SUCCEEDED(hr) && pAttrs) { bsType = GetAttr(pChild, pAttrs, L"type"); } if (SUCCEEDED(hr) && bsType) { if (!lstrcmpi(bsType, L"multi")) { // Тут значения хранятся так: //<value name="CmdLineHistory" type="multi"> // <line data="C:\Far\Far.exe"/> // <line data="cmd"/> //</value> wchar_t *pszData = NULL, *pszCur = NULL; size_t nMaxLen = 0, nCurLen = 0; long nCount = 0; if (pAttrs) { pAttrs->Release(); pAttrs = NULL; } // Получить все дочерние элементы нужного типа bsData = ::SysAllocString(L"line"); hr = pChild->selectNodes(bsData, &pList); ::SysFreeString(bsData); bsData = NULL; if (SUCCEEDED(hr) && pList) { hr = pList->get_length(&nCount); if (SUCCEEDED(hr) && (nCount > 0)) { HEAPVAL; nMaxLen = ((MAX_PATH+1) * nCount) + 1; pszData = (wchar_t*)malloc(nMaxLen * sizeof(wchar_t)); pszCur = pszData; pszCur[0] = 0; pszCur[1] = 0; nCurLen = 2; // сразу посчитать DoubleZero HEAPVAL; } } if (SUCCEEDED(hr) && pList) { hr = pList->reset(); while ((hr = pList->nextNode(&pNode)) == S_OK && pNode) { bsData = GetAttr(pNode, L"data"); pNode->Release(); pNode = NULL; if (SUCCEEDED(hr) && bsData) { nLen = _tcslen(bsData) + 1; if ((nCurLen + nLen) > nMaxLen) { // Нужно пересоздать! nMaxLen = nCurLen + nLen + MAX_PATH + 1; wchar_t *psz = (wchar_t*)malloc(nMaxLen * sizeof(wchar_t)); _ASSERTE(psz); if (!psz) break; // Не удалось выделить память! wmemmove(psz, pszData, nCurLen); pszCur = psz + (pszCur - pszData); HEAPVAL; free(pszData); pszData = psz; HEAPVAL; } lstrcpy(pszCur, bsData); pszCur += nLen; // указатель - на место для следующей строки nCurLen += nLen; *pszCur = 0; // ASCIIZZ HEAPVAL; ::SysFreeString(bsData); bsData = NULL; } } pList->Release(); pList = NULL; } // значит что-то прочитать удалось if (pszData) { if (*value) {free(*value); *value = NULL;} *value = pszData; lbRc = true; } } else if (!lstrcmpi(bsType, L"string")) { bsData = GetAttr(pChild, pAttrs, L"data"); if (SUCCEEDED(hr) && bsData) { nLen = _tcslen(bsData); if (!*value || (_tcslen(*value) <= nLen)) { *value = (wchar_t*)realloc(*value, (nLen+2)*sizeof(wchar_t)); } if (*value) { lstrcpy(*value, bsData); (*value)[nLen] = 0; // уже должен быть после lstrcpy (*value)[nLen+1] = 0; // ASCIIZZ lbRc = true; } } } // Все остальные типы - не интересуют. Нам нужны только строки } if (bsType) { ::SysFreeString(bsType); bsType = NULL; } if (bsData) { ::SysFreeString(bsData); bsData = NULL; } if (pChild) { pChild->Release(); pChild = NULL; } if (pAttrs) { pAttrs->Release(); pAttrs = NULL; } //if (!lbRc) //{ // _ASSERTE(*value == NULL); // *value = (wchar_t*)malloc(sizeof(wchar_t)*2); // (*value)[0] = 0; (*value)[1] = 0; // На случай REG_MULTI_SZ //} return lbRc; }
IXMLDOMNode* SettingsXML::FindItem(IXMLDOMNode* apFrom, const wchar_t* asType, const wchar_t* asName, bool abAllowCreate) { HRESULT hr = S_OK; IXMLDOMNodeList* pList = NULL; IXMLDOMNode* pChild = NULL; IXMLDOMNamedNodeMap* pAttrs = NULL; IXMLDOMAttribute *pIXMLDOMAttribute = NULL; IXMLDOMNode *pIXMLDOMNode = NULL; IXMLDOMNode *pName = NULL; BSTR bsText = NULL; BSTR bsCheck = NULL; DOMNodeType nodeTypeCheck = NODE_INVALID; BOOL lbEmpty = TRUE; int iLastIndent = 1; // Получить все дочерние элементы нужного типа if (apFrom == NULL) { hr = S_FALSE; } else { long lFound = 0; // key[@name="abc"], but it is case-sensitive, and may fails in theory bsText = lstrmerge(asType, L"[@name=\"", asName, L"\"]"); hr = apFrom->selectNodes(bsText, &pList); if (SUCCEEDED(hr) && pList) { hr = pList->get_length(&lFound); if (FAILED(hr) || (lFound < 1)) { SafeRelease(pList); } } SafeFree(bsText); // May be case-insensitive search will be succeeded? // However, it is very slow if (!pList) { bsText = ::SysAllocString(asType); hr = apFrom->selectNodes(bsText, &pList); ::SysFreeString(bsText); bsText = NULL; } } if (SUCCEEDED(hr) && pList) { hr = pList->reset(); while ((hr = pList->nextNode(&pIXMLDOMNode)) == S_OK && pIXMLDOMNode) { lbEmpty = FALSE; hr = pIXMLDOMNode->get_attributes(&pAttrs); if (SUCCEEDED(hr) && pAttrs) { bsText = GetAttr(pIXMLDOMNode, pAttrs, L"name"); if (bsText) { if (lstrcmpi(bsText, asName) == 0) { ::SysFreeString(bsText); bsText = NULL; pChild = pIXMLDOMNode; pIXMLDOMNode = NULL; break; } ::SysFreeString(bsText); bsText = NULL; } } pIXMLDOMNode->Release(); pIXMLDOMNode = NULL; } pList->Release(); //pList = NULL; -- для отладки } if (lbEmpty && abAllowCreate && (asType[0] == L'k')) { bsText = ::SysAllocString(L"value"); hr = apFrom->selectNodes(bsText, &pList); ::SysFreeString(bsText); bsText = NULL; if (SUCCEEDED(hr) && pList) { hr = pList->reset(); if ((hr = pList->nextNode(&pIXMLDOMNode)) == S_OK && pIXMLDOMNode) { lbEmpty = FALSE; pIXMLDOMNode->Release(); pIXMLDOMNode = NULL; } pList->Release(); //pList = NULL; -- для отладки } } if (!pChild && abAllowCreate) { if (asType[0] == L'k') { hr = apFrom->get_lastChild(&pChild); if (SUCCEEDED(hr) && pChild) { hr = pChild->get_nodeType(&nodeTypeCheck); if (SUCCEEDED(hr) && (nodeTypeCheck == NODE_TEXT)) { hr = pChild->get_text(&bsCheck); if (SUCCEEDED(hr) && bsCheck) { iLastIndent = 0; LPCWSTR pszTabs = bsCheck; while (*pszTabs) { if (*(pszTabs++) == L'\t') iLastIndent++; } ::SysFreeString(bsCheck); bsCheck = NULL; } } } SafeRelease(pChild); } VARIANT vtType; vtType.vt = VT_I4; vtType.lVal = NODE_ELEMENT; bsText = ::SysAllocString(asType); hr = mp_File->createNode(vtType, bsText, L"", &pChild); ::SysFreeString(bsText); bsText = NULL; if (SUCCEEDED(hr) && pChild) { if (SetAttr(pChild, L"name", asName)) { if (asType[0] == L'k') { AppendNewLine(pChild); mb_KeyEmpty = true; TouchKey(pChild); } if (asType[0] == L'k') { //if (mb_KeyEmpty) //AppendIndent(apFrom, lbEmpty ? (mi_Level-1) : mi_Level); AppendIndent(apFrom, (mi_Level-iLastIndent)); } else if (mb_KeyEmpty) { AppendIndent(apFrom, !lbEmpty ? (mi_Level-1) : mi_Level); } else { AppendIndent(apFrom, 1); } hr = apFrom->appendChild(pChild, &pIXMLDOMNode); pChild->Release(); pChild = NULL; if (FAILED(hr)) { pAttrs->Release(); pAttrs = NULL; } else { pChild = pIXMLDOMNode; pIXMLDOMNode = NULL; } AppendNewLine(apFrom); AppendIndent(apFrom, mi_Level-1); if ((asType[0] != L'k') && mb_KeyEmpty) mb_KeyEmpty = false; } else { pChild->Release(); pChild = NULL; } } } return pChild; }
string CKADmerge::GetPatternString(IXMLDOMNode * pXMLNode, BOOL bQuery) { HRESULT hRes = 0; string sPatternString = ""; string sElementName; if(pXMLNode) { // retrieve node name sElementName = GetName(pXMLNode); sPatternString = sElementName; if(SUCCEEDED(hRes)) { // retrieve all attributes IXMLDOMNodeList * pNodeList = NULL; BSTR bPatternString = NULL; bPatternString = ::SysAllocString(L"@*"); _bstr_t b2PatternString(bPatternString); hRes = pXMLNode->selectNodes(bPatternString, &pNodeList); ::SysFreeString(bPatternString); LONG lListLength = 0; hRes = pNodeList->get_length(&lListLength); if(SUCCEEDED(hRes) && lListLength) { // retrive attribute names IXMLDOMNode * pCurrentNode = NULL; hRes = pNodeList->nextNode(&pCurrentNode); string sAttributeName; while(pCurrentNode != NULL) { // attach attibute names and values to pattern string sAttributeName = GetName(pCurrentNode); if(!bQuery) { // all attributes if(sPatternString.find("[") == -1) { sPatternString += "["; } else { sPatternString += " and " ; } sPatternString += "@" + sAttributeName; sPatternString += "=\"" + ExpandBackslash(GetValue(pCurrentNode)) + "\""; } else { // just "primary key" (only first attribute) if(sPatternString.find("[") == -1) { sPatternString += "["; } sPatternString += "@" + sAttributeName; sPatternString += "=\"" + ExpandBackslash(GetValue(pCurrentNode)) + "\""; break; } hRes = pNodeList->nextNode(&pCurrentNode); } if(sPatternString.find("[") != -1) { sPatternString += "]"; } } if(pNodeList) pNodeList->Release(); } } return sPatternString; }
HRESULT CKADmerge::GetKADFilenames(string * sFilenames[], LONG &lLength, string sLogFile) { HRESULT hRes = S_FALSE; if(sLogFile != "") { // open log file OpenLog(sLogFile, sDescription + " GetKADFileNames"); } IXMLDOMNode * pXMLRoot = NULL; hRes = GetRootElement(m_pXMLKad, &pXMLRoot); if(hRes == S_OK) { // find elements IXMLDOMNodeList * pElemList = NULL; _bstr_t bPatternString("/KAD4CE/KERNEL/ADDON[@KADFILE]"); hRes = pXMLRoot->selectNodes(bPatternString, &pElemList); if(SUCCEEDED(hRes)) { LONG lElements = 0; pElemList->get_length(&lElements); (*sFilenames) = new string[lElements]; IXMLDOMNode * pCurrentElem = NULL; hRes = pElemList->nextNode(&pCurrentElem); int i = 0; while(pCurrentElem != NULL) { // find 'KADFILE' attribute IXMLDOMNodeList * pAttrList = NULL; _bstr_t bPatternString("@KADFILE"); hRes = pCurrentElem->selectNodes(bPatternString, &pAttrList); if(SUCCEEDED(hRes)) { LONG lAtributes = 0; pAttrList->get_length(&lAtributes); IXMLDOMNode * pCurrentAttr = NULL; hRes = pAttrList->nextNode(&pCurrentAttr); if(lAtributes == 1) { (*sFilenames)[i++] = GetValue(pCurrentAttr); } if(pCurrentAttr) pCurrentAttr->Release(); } hRes = pElemList->nextNode(&pCurrentElem); if(pAttrList) pAttrList->Release(); } lLength = i; hRes = S_OK; if(pCurrentElem) pCurrentElem->Release(); } if(pXMLRoot) pXMLRoot->Release(); if(pElemList) pElemList->Release(); } if(hRes == S_OK) { Log("GetKADFilenames:"); for(int i = 0; i < (int)lLength; i++) { Log((*sFilenames)[i]); } } // close log file CloseLog(); return hRes; }
HRESULT CKADmerge::CopyNode(IXMLDOMNode ** pXMLDest, IXMLDOMNode ** pXMLSrc, BOOL bOverwrite, string sPath) { HRESULT hRes = 0; IXMLDOMNodeList * pNodeList = NULL; if(*pXMLDest == NULL || *pXMLSrc == NULL) { Log("ERROR: CopyNode " + GetName(*pXMLSrc) + " to " + GetName(*pXMLDest)); hRes = S_FALSE; return hRes; } hRes = (*pXMLSrc)->get_childNodes(&pNodeList); if(SUCCEEDED(hRes)) { LONG lListLength = 0; hRes = pNodeList->get_length(&lListLength); IXMLDOMNode * pCurrentNode = NULL; hRes = pNodeList->nextNode(&pCurrentNode); while(pCurrentNode != NULL) { // iterate through the xml tree string sPatternString = GetPatternString(pCurrentNode, TRUE); IXMLDOMNode * pDestNode = NULL; BOOL bHasNode = HasNode(*pXMLDest, sPatternString, &pDestNode); if(bHasNode && (!m_Overwriteable[GetName(pCurrentNode)] || !bOverwrite )) { // copy child elements CopyNode(&pDestNode, &pCurrentNode, bOverwrite, sPath + "/" + sPatternString); } else if(bHasNode && m_Overwriteable[GetName(pCurrentNode)] && bOverwrite) { // compare element sPatternString = GetPatternString(pCurrentNode, TRUE); bHasNode = HasNode(*pXMLDest, sPatternString, &pDestNode); if(bHasNode) { sPatternString = GetPatternString(pCurrentNode, FALSE); bHasNode = HasNode(*pXMLDest, sPatternString, &pDestNode); if(!bHasNode) { // replace element IXMLDOMNode * pNewNode = NULL; IXMLDOMNode * pXMLOldChild = NULL; hRes = pCurrentNode->cloneNode(VARIANT_TRUE, &pNewNode); hRes = (*pXMLDest)->replaceChild(pNewNode, // new child pDestNode, // old child &pXMLOldChild); // out old child // log changes Log("Replace Element: " + sPath + "/" + sPatternString); if(pNewNode) pNewNode->Release(); if(pXMLOldChild) pXMLOldChild->Release(); m_bIsDirty = TRUE; } } } else if(!bHasNode) { // attach entire sub tree IXMLDOMNode * pDestNode = NULL; IXMLDOMNode * pXMLNewChild = NULL; hRes = pCurrentNode->cloneNode(VARIANT_TRUE, &pDestNode); hRes = (*pXMLDest)->appendChild(pDestNode, // new child &pXMLNewChild); // out new child // log changes sPatternString = GetPatternString(pCurrentNode, FALSE); Log("Attach Element: " + sPath + "/" + sPatternString); if(pDestNode) pDestNode->Release(); if(pXMLNewChild) pXMLNewChild->Release(); m_bIsDirty = TRUE; } hRes = pNodeList->nextNode(&pCurrentNode); } } return hRes; }
IXMLDOMNode* SettingsXML::FindItem(IXMLDOMNode* apFrom, const wchar_t* asType, const wchar_t* asName, bool abAllowCreate) { HRESULT hr = S_OK; IXMLDOMNodeList* pList = NULL; IXMLDOMNode* pChild = NULL; IXMLDOMNamedNodeMap* pAttrs = NULL; IXMLDOMAttribute *pIXMLDOMAttribute = NULL; IXMLDOMNode *pIXMLDOMNode = NULL; IXMLDOMNode *pName = NULL; BSTR bsText = NULL; BOOL lbEmpty = TRUE; // Получить все дочерние элементы нужного типа if (apFrom == NULL) { hr = S_FALSE; } else { bsText = ::SysAllocString(asType); hr = apFrom->selectNodes(bsText, &pList); ::SysFreeString(bsText); bsText = NULL; } if (SUCCEEDED(hr) && pList) { hr = pList->reset(); while((hr = pList->nextNode(&pIXMLDOMNode)) == S_OK && pIXMLDOMNode) { lbEmpty = FALSE; hr = pIXMLDOMNode->get_attributes(&pAttrs); if (SUCCEEDED(hr) && pAttrs) { bsText = GetAttr(pIXMLDOMNode, pAttrs, L"name"); if (bsText) { if (lstrcmpi(bsText, asName) == 0) { ::SysFreeString(bsText); bsText = NULL; pChild = pIXMLDOMNode; pIXMLDOMNode = NULL; break; } ::SysFreeString(bsText); bsText = NULL; } } pIXMLDOMNode->Release(); pIXMLDOMNode = NULL; } pList->Release(); //pList = NULL; -- для отладки } if (lbEmpty && abAllowCreate && (asType[0] == L'k')) { bsText = ::SysAllocString(L"value"); hr = apFrom->selectNodes(bsText, &pList); ::SysFreeString(bsText); bsText = NULL; if (SUCCEEDED(hr) && pList) { hr = pList->reset(); if ((hr = pList->nextNode(&pIXMLDOMNode)) == S_OK && pIXMLDOMNode) { lbEmpty = FALSE; pIXMLDOMNode->Release(); pIXMLDOMNode = NULL; } pList->Release(); //pList = NULL; -- для отладки } } if (!pChild && abAllowCreate) { VARIANT vtType; vtType.vt = VT_I4; vtType.lVal = NODE_ELEMENT; bsText = ::SysAllocString(asType); hr = mp_File->createNode(vtType, bsText, L"", &pChild); ::SysFreeString(bsText); bsText = NULL; if (SUCCEEDED(hr) && pChild) { if (SetAttr(pChild, L"name", asName)) { if (asType[0] == L'k') { AppendNewLine(pChild); mb_KeyEmpty = true; } if (asType[0] == L'k') { //if (mb_KeyEmpty) //AppendIndent(apFrom, lbEmpty ? (mi_Level-1) : mi_Level); AppendIndent(apFrom, (mi_Level-1)); } else if (mb_KeyEmpty) { AppendIndent(apFrom, !lbEmpty ? (mi_Level-1) : mi_Level); } else { AppendIndent(apFrom, 1); } hr = apFrom->appendChild(pChild, &pIXMLDOMNode); pChild->Release(); pChild = NULL; if (FAILED(hr)) { pAttrs->Release(); pAttrs = NULL; } else { pChild = pIXMLDOMNode; pIXMLDOMNode = NULL; } AppendNewLine(apFrom); AppendIndent(apFrom, mi_Level-1); if ((asType[0] != L'k') && mb_KeyEmpty) mb_KeyEmpty = false; } else { pChild->Release(); pChild = NULL; } } } return pChild; }