如何使用MSXML C++实现向已有XML文档添加子XML内容(替代CMarkup的addsubdoc功能)
解决MSXML中添加子XML文档到现有节点的问题
我来帮你排查代码里的几个关键问题,然后给出修复后的完整解决方案:
问题分析
你的代码里有几个直接导致操作失败的原因:
- 变量名错误:创建
pXMLDom1实例时,你写的是pXMLDom.CreateInstance,但变量名是pXMLDom1,这会导致pXMLDom1未初始化,后续所有XML操作都会失效。 - 根节点获取逻辑错误:
GetfirstChild()返回的是XML声明节点(<?xml...?>),这个节点没有baseName属性,所以你拿到的root是空值,selectSingleNode(root)自然找不到目标的<Book>节点。 - 传递错误的节点类型:你直接把整个
pXMLDom2文档对象传给appendChild,但MSXML要求添加的必须是元素节点,而不是文档对象本身,需要提取子文档的根元素再进行添加。
修复后的完整代码
#import <msxml6.dll> #include "msxml2.h" #include <iostream> #include <atlstr.h> void main() { MSXML2::IXMLDOMDocumentPtr pXMLDom1; MSXML2::IXMLDOMDocumentPtr pXMLDom2; // 修复变量名错误:使用pXMLDom1创建实例 HRESULT hr = pXMLDom1.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER); HRESULT hr2 = pXMLDom2.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER); // 检查实例是否创建成功 if (FAILED(hr) || FAILED(hr2)) { printf("Failed to create DOM instances\n"); return; } CString str = L"<?xml version=\"1.0\" encoding=\"utf-16\"?>" L"<Book>" L"<Text>" L"<Name>CPP</Name>" L"<Author>Henry</Author>" L"</Text>" L"</Book>"; CString sub = L"<Text>" L"<Name>5656</Name>" L"<Author>Steve</Author>" L"</Text>"; // 禁用异步加载,确保XML同步加载完成 pXMLDom1->async = VARIANT_FALSE; pXMLDom2->async = VARIANT_FALSE; VARIANT_BOOL loadSuccess1 = pXMLDom1->loadXML(_bstr_t(str)); VARIANT_BOOL loadSuccess2 = pXMLDom2->loadXML(_bstr_t(sub)); if (!loadSuccess1 || !loadSuccess2) { printf("Failed to load XML content\n"); return; } printf("Original DOM:\n%s\n", static_cast<PCSTR>(pXMLDom1->xml)); printf("Sub DOM:\n%s\n", static_cast<PCSTR>(pXMLDom2->xml)); // 直接获取文档根元素<Book>,这是最可靠的方式 MSXML2::IXMLDOMNodePtr pBookNode = pXMLDom1->documentElement; if (!pBookNode) { printf("Failed to get Book node\n"); return; } // 提取子文档的根元素<Text>,而不是传递整个文档对象 MSXML2::IXMLDOMNodePtr pSubTextNode = pXMLDom2->documentElement; if (!pSubTextNode) { printf("Failed to get sub Text node\n"); return; } // 将子节点添加到<Book>节点下 MSXML2::IXMLDOMNodePtr pAddedNode = pBookNode->appendChild(pSubTextNode); if (!pAddedNode) { printf("Failed to append child node\n"); return; } printf("Merged XML:\n%s\n", static_cast<PCSTR>(pXMLDom1->xml)); }
关键修复点说明
- 修正变量名:把创建
pXMLDom1实例的代码改成pXMLDom1.CreateInstance,确保XML文档对象初始化成功。 - 可靠获取根节点:使用
documentElement属性直接获取文档的根元素(也就是<Book>),这个方法会自动跳过XML声明、注释等非元素节点,比GetfirstChild()更稳定。 - 提取子文档的元素节点:通过
pXMLDom2->documentElement拿到子文档的<Text>节点,再把这个元素节点传给appendChild,而不是传递整个文档对象。 - 添加加载检查:开启
async = VARIANT_FALSE并检查loadXML的返回值,确保XML内容加载成功,避免后续操作在无效对象上执行。
修改后你会得到期望的XML结构:
<Book> <Text> <Name>CPP</Name> <Author>Henry</Author> </Text> <Text> <Name>5656</Name> <Author>Steve</Author> </Text> </Book>
内容的提问来源于stack exchange,提问作者DevPy
相关产品推荐
相关产品推荐

