对于使用C++语言,CMarkup由于其灵活、快速的特点,成为很多程序员用来解析XML的一个工具。
但是,由于免费版本不支持XPATH的查找,在Free版本中,当需要在一个XML中定位某个节点时,需要不断的IntoElem,FindElem,很不方便。所以,花了一个下午的时间,特意改写了一个CMarkup类,使其支持以下任意定位和绝对定位的查找:
markup.FindItem("//Item"); / 任意定位 /
markup.FindItem("/ROOT/ITEMS/ITEM"); / 绝对定位 /
主要改写的点在以下两个函数:
CMarkup::FindElem() 和 CMarkup::x_FindElem()
改写后的代码如下所示:
1boolCMarkup::FindElem( MCD_CSTR szName )
2{
3if( m_nDocFlags&MDF_WRITEFILE )
4returnfalse;
5if( m_pElemPosTree->GetSize() )
6{
7//Change current position only if found
8PathPos path( szName,false);
9if(path.IsAbsolutePath()) {/绝对路径查找时,XML定位到开始位置/
10ResetPos();
11}
12intiPos=x_FindElem( m_iPosParent, m_iPos, path );
13if( iPos )
14{
15//Assign new position
16x_SetPos( ELEM(iPos).iElemParent, iPos,0);
17returntrue;
18}
19}
20returnfalse;
21}
1intCMarkup::x_FindElem(intiPosParent,intiPos, 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//
6if(!path.ValidPath() )
7return0;
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
13if( iPos )
14iPos=ELEM(iPos).iElemNext;
15else
16iPos=ELEM(iPosParent).iElemChild;
17
18//Finished here if pPath not specified
19if(!path.IsPath() )
20returniPos;
21
22//Search
23MCD_PCSZ strTmp;
24intiParent=iPos;
25intiOldPos=0;
26TokenPos token( m_strDoc, m_nDocFlags );
27if(path.IsAbsolutePath()||path.IsAnywherePath())/取得查找的路径, 删除查找字符串前面的 '/' 符号/
28strTmp=path.GetWordAndInc();
29while( iPos )
30{
31//Compare tag name
32token.m_nNext=ELEM(iPos).nStart+1;
33token.FindName();//Locate tag name
34if( token.Match(strTmp) )
35{
36if(path.IsAtPathEnd())/针对绝对路径查找,查找到最后一个Token时返回/
37{
38returniPos;/匹配成功/
39}
40else
41{
42path.IncChar();
43strTmp=path.GetWordAndInc();/针对绝对路径查找,剥离一个路径。如 [ROOT/ITEMS/ITEM] →[ITEMS/ITEM]/
44iPos=ELEM(iPos).iElemChild;
45continue;
46}
47}
48else{
49path.IncChar();
50iOldPos=iPos;
51iPos=ELEM(iPos).iElemChild;/当前节点无法匹配,进入子节点进行匹配/
52if(iPos)
53continue;
54else
55iPos=iOldPos;
56if( path.IsAtPathEnd() )
57iPos=ELEM(ELEM(iPos).iElemParent).iElemNext;/子节点无法匹配,向邻居节点进行匹配/
58continue;
59}
60iPos=ELEM(iPos).iElemNext;
61}
62return0;
63
64}
以上、一时还有一些没考虑到的情况,不过经过一些简单测试,至少是可以使用的。
原文链接: https://www.cnblogs.com/shipfi/archive/2010/11/29/1891243.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/18070
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!