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; }
bool SettingsXML::SetMultiLine(IXMLDOMNode* apNode, const wchar_t* asValue, long nAllLen) { bool bRc = false; HRESULT hr; VARIANT_BOOL bHasChild = VARIANT_FALSE; DOMNodeType nodeType = NODE_INVALID; BSTR bsNodeType = ::SysAllocString(L"line"); VARIANT vtType; vtType.vt = VT_I4; vtType.lVal = NODE_ELEMENT; IXMLDOMNode* pNode = NULL; IXMLDOMNode* pNodeRmv = NULL; long nLen = 0; const wchar_t* psz = asValue; bool bNewNodeCreate = false; int iAddIndent = 1; bool bAddFirstNewLine = false; hr = apNode->get_firstChild(&pNode); if (pNode == NULL) { bAddFirstNewLine = true; iAddIndent = mi_Level + 1; } // Обновляем существующие while ((psz && *psz && nAllLen > 0) && (SUCCEEDED(hr) && pNode)) { hr = pNode->get_nodeType(&nodeType); if (SUCCEEDED(hr) && (nodeType == NODE_ELEMENT)) { if (!SetAttr(pNode, L"data", psz)) goto wrap; nLen = _tcslen(psz)+1; psz += nLen; nAllLen -= nLen; } hr = pNode->get_nextSibling(&pNode); } // Добавляем что осталось while (psz && *psz && nAllLen > 0) { hr = mp_File->createNode(vtType, bsNodeType, L"", &pNode); if (FAILED(hr) || !pNode) goto wrap; if (!SetAttr(pNode, L"data", psz)) goto wrap; if (bAddFirstNewLine) { AppendNewLine(apNode); bAddFirstNewLine = false; } AppendIndent(apNode, iAddIndent); hr = apNode->appendChild(pNode, &pNodeRmv); AppendNewLine(apNode); bNewNodeCreate = true; iAddIndent = mi_Level + 1; SafeRelease(pNode); SafeRelease(pNodeRmv); if (FAILED(hr)) goto wrap; nLen = _tcslen(psz)+1; psz += nLen; nAllLen -= nLen; } // Очистить хвост (если элементов стало меньше) if (pNode) { ClearChildrenTail(apNode, pNode); AppendNewLine(apNode); bNewNodeCreate = true; } if (bNewNodeCreate) { AppendIndent(apNode, mi_Level); } bRc = true; wrap: _ASSERTE(nAllLen <= 1); ::SysFreeString(bsNodeType); return bRc; }
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; }