CMarkup免费版的一些扩展

Posted on 2010-08-10 10:01  一有新人  阅读(1826)  评论(1)    收藏  举报

最近,在工作中需要分析XML,并对XML内容作出一定的修改。

在网上找到一个XML解析的类,CMarkup(来自http://www.firstobject.com/)。开始用来感觉不错,但是随着开发的深入,CMarkup的免费版本已经不能满足我的要求了。(老外真是有版权意识啊,CMarkup的Developer 版本要收¥249)没办法,只能自己来写了。

于是写了一个类,继承自CMarkup,在其中实现了我所需要的功能(还比较粗糙,就不放上来了)。通过研究,对CMarkup的存储结构有了一定的了解。如果有误,请大牛些指正。

在CMarkup中,xml文档数据存储在 protected 成员变量MCD_STR m_strDoc中,可通过Load()或者SetDoc()函数来对其进行设定。在操作的时候,CMarkup将m_strDoc当做一棵树来处理。结点的信息存储在protected 成员变量ElemPosTree* m_pElemPosTree中。ElemPosTree是一个结构体,它的内容如下:

 

ElemPosTree结构体
struct ElemPosTree
{
    ElemPosTree() { Clear(); };
    
~ElemPosTree() { Release(); };
    
enum { PA_SEGBITS = 16, PA_SEGMASK = 0xffff };
    
void ReleaseElemPosTree() { Release(); Clear(); };
    
void Release() { for (int n=0;n<SegsUsed();++n) delete[] (char*)m_pSegs[n]; if (m_pSegs) delete[] (char*)m_pSegs; };
    
void Clear() { m_nSegs=0; m_nSize=0; m_pSegs=NULL; };
    
int GetSize() const { return m_nSize; };
    
int SegsUsed() const { return ((m_nSize-1)>>PA_SEGBITS) + 1; };
    ElemPos
& GetRefElemPosAt(int i) const { return m_pSegs[i>>PA_SEGBITS][i&PA_SEGMASK]; };
    
void CopyElemPosTree( ElemPosTree* pOtherTree, int n );
    
void GrowElemPosTree( int nNewSize );
private:
    ElemPos
** m_pSegs;    //这就是树的存储结构了
    int m_nSize;
    
int m_nSegs;
};

 

其中ElemPos是一个结构体,它存储了结点的信息:

 

ElemPos结构体
struct ElemPos
{
    ElemPos() {};
    ElemPos( 
const ElemPos& pos ) { *this = pos; };
    
int StartTagLen() const { return nStartTagLen; };
    
void SetStartTagLen( int n ) { nStartTagLen = n; };
    
void AdjustStartTagLen( int n ) { nStartTagLen += n; };
    
int EndTagLen() const { return nEndTagLen; };
    
void SetEndTagLen( int n ) { nEndTagLen = n; };
    
bool IsEmptyElement() { return (StartTagLen()==nLength)?true:false; };
    
int StartContent() const { return nStart + StartTagLen(); };
    
int ContentLen() const { return nLength - StartTagLen() - EndTagLen(); };
    
int StartAfter() const { return nStart + nLength; };
    
int Level() const { return nFlags & 0xffff; };
    
void SetLevel( int nLev ) { nFlags = (nFlags & ~0xffff| nLev; };
    
void ClearVirtualParent() { memset(this,0,sizeof(ElemPos)); };
    
void SetEndTagLenUnparsed() { SetEndTagLen(1); };
    
bool IsUnparsed() { return EndTagLen() == 1; };

    
// Memory size: 8 32-bit integers == 32 bytes
    int nStart;
    
int nLength;
    unsigned 
int nStartTagLen : 22// 4MB limit for start tag
    unsigned int nEndTagLen : 10// 1K limit for end tag
    int nFlags; // 16 bits flags, 16 bits level 65536 depth limit
    int iElemParent;
    
int iElemChild; // first child
    int iElemNext; // next sibling
    int iElemPrev; // if this is first, iElemPrev points to last
};

 

 

结构体ElemPos很关键,对它的成员变量说明如下:

nStart   代表标签在m_strDoc中的起始位置;

nLength  代表标签的长度(以"/>"结束或者以"</xxx>"结束)

nStartTagLen  代表标签的开始部分的长度(以byte计)

nEndTagLen  代表标签结束部分的长度(以byte计)

其它成员有待研究

举例说明如下:

<root><tag1>value</tag1></root>

 

假设上面的内容就是我们的XML,即m_strDoc="<root><tag1>value</tag1></root>"

则root标签编号为0,tag1标签编号为1。

对存储tag1标签的结点来说,nStart为6,nLength为18("<tag1>value</tag1>"的长度),nStartTagLen为6("<tag1>"的长度),nEndTagLen为7("</tag1>"的长度)。

 

现在清晰了,其实 CMarkup的内部结构就是虚拟的一棵树,内容是存储在m_strDoc中的,标签的位置信息存储在ElemPosTree结构体中。知道了它的存储结构,以后想扩展CMarkup就容易多了。

 

 

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3