CMarkup的改进

对于使用C++语言,CMarkup由于其灵活、快速的特点,成为很多程序员用来解析XML的一个工具。

但是,由于免费版本不支持XPATH的查找,在Free版本中,当需要在一个XML中定位某个节点时,需要不断的IntoElem,FindElem,很不方便。所以,花了一个下午的时间,特意改写了一个CMarkup类,使其支持以下任意定位和绝对定位的查找:

   markup.FindItem("//Item");                      /* 任意定位 */

   markup.FindItem("/ROOT/ITEMS/ITEM");   /* 绝对定位 */

 

主要改写的点在以下两个函数:

   CMarkup::FindElem()  和 CMarkup::x_FindElem()

 

 改写后的代码如下所示:

 1  bool  CMarkup::FindElem( MCD_CSTR szName )
 2  {
 3       if  ( m_nDocFlags  &  MDF_WRITEFILE )
 4           return   false ;
 5       if  ( m_pElemPosTree -> GetSize() )
 6      {
 7           //  Change current position only if found
 8          PathPos path( szName,  false  );
 9           if (path.IsAbsolutePath()) {    /*  绝对路径查找时,XML定位到开始位置  */
10              ResetPos();
11          }
12           int  iPos  =  x_FindElem( m_iPosParent, m_iPos, path );
13           if  ( iPos )
14          {
15               //  Assign new position
16              x_SetPos( ELEM(iPos).iElemParent, iPos,  0  );
17               return   true ;
18          }
19      }
20       return   false ;
21  }


 

 1  int  CMarkup::x_FindElem(  int  iPosParent,  int  iPos, PathPos &  path )  const
 2  {
 3       //  If pPath is NULL or empty, go to next sibling element
 4       //  Otherwise go to next sibling element with matching path
 5       //
 6       if  (  !  path.ValidPath() )
 7           return   0 ;
 8 
 9       //  Paths other than simple tag name are only supported in the developer version
10  //     if ( path.IsAnywherePath() || path.IsAbsolutePath() )   /* 原有功能针对绝对定位及任意定位查找时,直接返回. */
11  //         return 0;
12 
13       if  ( iPos )
14          iPos  =  ELEM(iPos).iElemNext;
15       else
16          iPos  =  ELEM(iPosParent).iElemChild;
17 
18       //  Finished here if pPath not specified
19       if  (  !  path.IsPath() )
20           return  iPos;
21 
22       //  Search
23      MCD_PCSZ strTmp;
24       int  iParent  =  iPos;
25       int  iOldPos  =   0 ;
26      TokenPos token( m_strDoc, m_nDocFlags );
27       if (path.IsAbsolutePath()  ||  path.IsAnywherePath())    /*   取得查找的路径, 删除查找字符串前面的 '/' 符号  */
28          strTmp  =  path.GetWordAndInc();
29       while  ( iPos )
30      {
31           //  Compare tag name
32          token.m_nNext  =  ELEM(iPos).nStart  +   1 ;
33          token.FindName();  //  Locate tag name
34           if  ( token.Match(strTmp) )
35          {
36               if  (path.IsAtPathEnd())    /*   针对绝对路径查找,查找到最后一个Token时返回  */
37              {    
38                   return  iPos;    /*   匹配成功  */
39              }
40               else
41              {
42                  path.IncChar();
43                  strTmp  =  path.GetWordAndInc();    /*   针对绝对路径查找,剥离一个路径。如 [ROOT/ITEMS/ITEM] →[ITEMS/ITEM]   */
44                  iPos  =  ELEM(iPos).iElemChild;
45                   continue ;
46              }
47          }
48           else  {
49               path.IncChar();
50               iOldPos  =  iPos;
51               iPos  =  ELEM(iPos).iElemChild;   /*  当前节点无法匹配,进入子节点进行匹配  */
52                if (iPos)
53                     continue ;
54                else
55                    iPos  =  iOldPos;
56                if ( path.IsAtPathEnd() ) 
57                    iPos  =  ELEM(ELEM(iPos).iElemParent).iElemNext;   /*  子节点无法匹配,向邻居节点进行匹配  */
58                continue ;
59          }
60          iPos  =  ELEM(iPos).iElemNext;
61      }
62       return   0 ;
63 
64  }


以上、一时还有一些没考虑到的情况,不过经过一些简单测试,至少是可以使用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值