一个XML比较器

XMLCompare可对2XML进行比较,比较是忽略兄弟节点间的顺序的,只对包含关系和属性进行比较。

写着个程序的目的本来是为了测试我写的一个XML Parser解析结果是否正确。不过这个比较器也可以用于比较其他XML,利用STL中的map和set来存储属性和父子关系,可以轻松实现2个XML在层次逻辑上的比较(不考虑兄弟之间的顺序)。

#include <iostream>
#include <tchar.h>
#include <map>
#include <set>
#include <string>
#include <stack>
#import <msxml4.dll>
using namespace std;

stack <wstring> errpath;

inline void TESTHR( HRESULT _hr )
{ if FAILED(_hr) throw(_hr); }


struct Node
{
 map<wstring, wstring> m_mattributes;
 multiset<Node> m_childNodes;
 wstring text;
 wstring name;
 bool operator < (const Node& node) const
 {
  if(name < node.name)
   return true;
  if(m_mattributes < node.m_mattributes)
   return true;
  
  if(text < node.text)
   return true;

  if(m_childNodes < node.m_childNodes)
   return true;

  return false;

 }
 bool operator == (const Node& node) const
 {
  if(name == node.name && m_mattributes == node.m_mattributes &&
   text == node.text && m_childNodes == node.m_childNodes)
   return true;
  else
  {
   wstring s = name;
   if(m_mattributes.size() > 0)
   {
    s.append(L"[");
    for(map<wstring, wstring>::const_iterator pos=m_mattributes.begin();
     pos!=m_mattributes.end(); ++pos){
      s.append(L"@");
      s.append(pos->first);
      s.append(L"='");
      s.append(pos->second);
      s.append(L"',");

     }
    s.erase(s.size()-1, 1);
    s.append(L"]");
     
   }
   errpath.push(s);
            return false;
  }

 }
};


void DOMToNode(MSXML2::IXMLDOMNodePtr nodeptr, Node& parent)
{
 Node node;

 if(nodeptr->nodeType == NODE_TEXT){
  node.text = nodeptr->text;
  parent.m_childNodes.insert(node);
  return;
 }

 node.name = nodeptr->nodeName;

 map <wstring, wstring> &pm = node.m_mattributes;

 MSXML2::IXMLDOMNamedNodeMapPtr mapPtr = nodeptr->attributes;

 if (mapPtr == NULL) return;
 unsigned int len = mapPtr->length;

 MSXML2::IXMLDOMNodePtr tmp;
 for(unsigned int i = 0; i<len; ++i) {
  tmp = mapPtr->item[i];

  pm[wstring(tmp->nodeName)] =
   wstring((_bstr_t)tmp->nodeValue );
 }

 MSXML2::IXMLDOMNodeListPtr pXMLDomNodeList = NULL;
 pXMLDomNodeList = nodeptr->childNodes;
 if(pXMLDomNodeList != NULL && pXMLDomNodeList->length > 0) {
        while(!FAILED(pXMLDomNodeList->raw_nextNode(&tmp)) && (tmp != NULL)){
   DOMToNode(tmp, node);
  }
 }

 parent.m_childNodes.insert(node);

}

bool compare_xml(TCHAR* fn1, TCHAR* fn2)
{
 MSXML2::IXMLDOMDocumentPtr xdoc1ptr, xdoc2ptr;

 try{
  TESTHR(CoInitialize(NULL));
  TESTHR(xdoc1ptr.CreateInstance(__uuidof(MSXML2::DOMDocument40)));
  TESTHR(xdoc2ptr.CreateInstance(__uuidof(MSXML2::DOMDocument40)));
  xdoc1ptr->load(_variant_t(fn1));
  xdoc2ptr->load(_variant_t(fn2));
  Node nd1,nd2;
  DOMToNode(xdoc1ptr->documentElement, nd1);
  DOMToNode(xdoc2ptr->documentElement, nd2);

  if( nd1 == nd2 )
   return true;
  else
   return false;
 }
 catch(TCHAR* errmsg){
  cerr << errmsg << endl;
  xdoc1ptr = xdoc2ptr = NULL;
  CoUninitialize();
 }
 catch(...){
  cerr << "unknown error occur" << endl;
  xdoc1ptr = xdoc2ptr = NULL;
  CoUninitialize();
 }
 return false;
}

int _tmain(int argc, _TCHAR* argv[])
{
 if(argc < 3)
 {
  cout << "too few parameter" << endl;
  return 0;
 }
 locale loc("chs");
 wcout.imbue(loc);

 if(compare_xml(argv[1], argv[2]))
  cout << "compare OK" << endl;
 else
 {

        cout << "compare failed" << endl;
  wcout << "on node: ";
  while(errpath.size() > 0){
   
   wcout << "/" << errpath.top();
   errpath.pop();
  }
  wcout << endl;
 }
 CoUninitialize();
 return 0;
}

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值