[经验总结]利用MSXML在不同DOM树之间拷贝结点

首先还是看一段代码:

// 拷贝XML结点 BOOL CPrintQuestionDlg::CopyXMLNode(CComPtr<IXMLDOMDocument> spDocSrc, const CString& strXpathSrc, CComPtr<IXMLDOMDocument> spDocDest, const CString& strXpathDest) { CComPtr<IXMLDOMNodeList> spNodeListSrc; // 内容来源结点集(有可能取得多个结点) CComPtr<IXMLDOMNode> spNodeDest; // 模板中需要填充的结点 // strXpathSrc取属性结点时一定要加text()函数,不然取不到结点 spDocSrc->selectNodes((CComBSTR)strXpathSrc,&spNodeListSrc); if (NULL == spNodeListSrc) return FALSE; spDocDest->selectSingleNode((CComBSTR)strXpathDest,&spNodeDest); if (NULL == spNodeDest) return FALSE; long iLength; spNodeListSrc->get_length(&iLength); for (int i = 0; i < iLength; i++) { CComPtr<IXMLDOMNode> spChildNode; spNodeListSrc->get_item(i, &spChildNode); // 取子结点 ASSERT(spChildNode != NULL); // 因为appendChild函数 // HRESULT appendChild( // IXMLDOMNode *newChild, // IXMLDOMNode **outNewChild); // 具有特性:If newChild has an existing parent, the node is automatically removed from that parent before being inserted into its new location. // 所以在添加结点之前先复制结点 CComPtr<IXMLDOMNode> spCloneNode; spChildNode->cloneNode(VARIANT_TRUE, &spCloneNode); ASSERT(spCloneNode != NULL); spNodeDest->appendChild(spCloneNode,NULL); // 跨DOM树添加结点(保留命名空间) } return TRUE;

写这段代码的目的是想从不同XML/HTML 文件抽取信息拼接成一个打印页面(HTML),类似于报表打印的功能。 实现利用XPath语句提取源路径中的所有子结点,将其添加到目标路径下。实现时遇到两个难点,第一个是IXMLDOMDocument不支持命名空间,也就是说IXMLDOMDocument类型的文档结点对象不支持带命名空间的路径导航。微软的东西做得很奇怪,//Xpath 这个路径居然可以深入到带命名空间的路径中查找查找,这是与XPath标准不符合的,但却能方便用//anyNode 这样的方式提取带命名空间的结点。我们用到selectNodes,所以提取属性结点时需要在最后加一个text()函数。另外需要注意的是从当前结点出来访问路径需要加一个点(.),不然会根结点开始访问。 每二个难点跨DOM树添加结点,没想到appendChild直接支持这个功能,只不过调用方式比较特殊,非得在后面加个NULL参数。被添加的结点其命名空间 不变。

最近经常用MSXML,相对于以前使用的Libxml,这一套API设计得还是比较方便,但是因为微软一贯的传统不开放源代码,很多细节文档中说不清或者干脆不提及,所以实现过程有1/3的时间是在与这些未知的细节斗争。还是怀念使用Libxml的日子,花一下午时间研究研究Libxml库的基本数据结构,以前遇到问题就能迎韧而解,还能根据实际情况灵活调用API。因为开源,所以能对其数据结构、实现方式做心中有数,进而能心中有沟壑,键下自风云。


突然又想起Eric Raymond笔下的那个猪小兵:" 一切都要比他想的费时和痛苦。在程序库表面光鲜的示例程序下,正在重用的组件似乎在一些边界情况下表现得无法预料或具有破坏性--而这些边界情况在他的代码中常遇到。小兵经常奇怪写程序库的家伙是怎么想的。但他没法知道,因为组件的文档不全--那些文档是技术文员写的,他们既不是程序员,想问题的方式也不像程序员。他也不能通过阅读源码来了解程序究竟是干什么的,因为程序库是处于专有许可证下不透明的目标码。“

Windows程序员遇到很多麻烦(编码效率和质量方面)和猪小兵一样的,这些问题归根结底是透明性。微软提供的API都缺乏透明性,很多人捧着MSDN沾沾自喜,却不知项目的灾难来自那里。我们无法修正不通内情的东西。实际上,任何规模大一些的API,如果无法看到源代码,是无法正确使用的。只有文档,还不能指导实践。文档并不能传达代码的所有细微差别之处,而“魔鬼”恰巧是隐藏在细节之中。

抱怨归抱怨,工作还是得干好。Windows的闭源开发方式应该也有一定规律,接下来得看看别人是怎么做的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值