初始化
Load 从一个(xml)文件构建CMarkup对象并对其进行解析。
SetDoc 从一个字符串构建CMarkup对象并对其进行解析。
输出
Save 把xml文档数据写到文件中。
GetDoc 将整个xml文档数据作为一个字符串返回。
改变当前位置
FindElem 定位到下一个元素,可以选择匹配标签名或者路径。
FindChildElem 定位到下一个子元素,可以选择匹配标签名或者路径。
FindNode 定位到下一个节点,可选择匹配节点类型。
IntoElem 进入当前位置的下一级位置,而当前位置则变为父位置。
OutOfElem 使当前位置的父位置变为当前位置。
ResetPos 复位当前位置为文档的起始位置。
ResetMainPos 复位当前位置为第一个兄弟位置之前。
ResetChilePos 复位当前的子位置为第一个子位置之前。
添加元素
AddElem 在当前位置元素或者最后一个兄弟之后新增一个元素。
InsertElem 在当前位置元素或者第一个兄弟之前插入一个元素。
AddChildElem 在当前子位置元素或者最后一个子位置之后增加一个元素。
InsertChildElem在当前子位置元素或者第一个子位置之前插入一个元素。
AddSubDoc 在当前位置元素或者最后一个兄弟之后新增一个子文档。
InsertSubDoc 在当前位置元素或者第一个兄弟之前新增一个子文档。
AddChildSubDoc在当前子位置元素或者最后一个子位置之后增加一个子文档。
InsertChildSubDoc在当前子位置元素或者第一个子位置之前插入一个子文档。
AddNode 在当前节点的后面或者父元素内容的末尾新增一个节点。
InsertNode在当前节点的前面或者父元素内容的开头新增一个节点。
(译注:注意区分元素和节点,元素只是一种特殊的节点而已。)
删除元素
RemoveElem 删除当前位置元素,包括子元素。
RemoveChildElem 删除当前位置的子元素,包括子元素的子元素。
RemoveNode 删除当前节点。 RemoveAttrib 从当前位置的元素中删除指定的属性
RemoveChildAttrib的子 从当前位置的子元素中删除指定的属性
获取数据
GetData 返回当前位置元素或者节点的字符串值。
GetChildData 返回当前子位置元素的字符串值。
GetElemContent 返回当前位置包括子位置的markup字符串内容
GetSubDoc 返回当前位置包括子位置的子文档markup字符串内容
GetChildSubDoc 返回当前子位置包括其子位置的子文档markup字符串内
GetAttrib 获得当前位置某指定的具体属性的字符串值
GetChildAttrib 获得当前子位置某指定的具体属性的字符串值
GetTagName 获得当前位置的标签的名称
GetChildTagName 获得当前子位置的标签的名称
设置值,修改数据
SetData 设置当前位置元素或者节点的值
SetChildData 设置当前子位置元素的值
SetElemContent 将当前位置元素用markup(标记)内容来替换
SetAttrib 设置当前位置元素的指定属性的值
SetChildAttrib 设置当前子位置元素的指定属性的值
获取其它信息
GetNthAttrib 通过传入属性的索引获得当前位置指定的属性名称和属性值(译注:所谓属性的索引就是0~n-1这样递增序列,n表示属性的数量)
GetAttribName 通过传入属性的索引获得当前位置指定的属性名称
GetNodeType 返回当前节点的节点类型
获取位置信息
SavePos 使用一个可选的字符串把当前位置保存到一个hash map中
RestorePos 定位到通过SavePos保存的位置
SetMapSize 设置SavePos和RestorePos可以使用hash map的大小
文档状态信息
IsWellFormed 判断是否仅有单一的根元素并且恰当得容纳元素
GetResult 返回最后一次解析或者文件操作后结果的xml字符串(译注:类似于错误码)
GetError 返回最后一次解析或者文件操作后的结果描述字符串
GetDocFlags 返回文档标志
SetDocFlags 设置文档标志
静态通用函数
ReadTextFile 读取一个文本文件并转换为字符串
WriteTextFile 将字符串写到一个文本文件中
GetDeclaredEncoding 从XML的声明中获得编码的字符串名称
EscapeText 返回把特殊字符(xml特殊字符)编码过的字符串
UnescapeText 返回把特殊字符(xml特殊字符)解码过的字符串
UTF8ToA 将UTF-8字符串转换成非Unicode(例如ANSI)字符串
AToUTF8 将非Unicode(例如ANSI)字符串转换成UTF-8字符串
UTF16To8 将UTF-16字符串转换成UTF-8字符串
UTF8To16 将UTF-8字符串转换成UTF-16字符串
GetDoc
.可以得到它。
AddElem
创建根元素。.在这个位置,如果你调用
AddElem("ORDER")
,你的文档会简单的装一个空ORDER元素
<
ORDER
/>
. 然后调用
AddChildElem
在根元素的下面创建元素 (例如:“进入”根元素内部,层次表示).下面的示例代码创建一个XML文档并返回它(的内容)到一个字符串中。
CMarkup xml;
xml.AddElem( "ORDER" );
xml.AddChildElem( "ITEM" );
xml.IntoElem();
xml.AddChildElem( "SN", "132487A-J" );
xml.AddChildElem( "NAME", "crank casing" );
xml.AddChildElem( "QTY", "1" );
CString csXML = xml.GetDoc();
<
ORDER
>
在开头,结束标签
</
ORDER
>
在结尾。当一个元素是在一个父下面(深入或被包含),这个父元素的开始标签要在它之前,结束标签要在它之后。ORDER元素包含一个ITEM元素,而ITEM元素包含了三个字子元素:SN、NAME和QTY;
<ORDER>
<ITEM>
<SN>132487A-J</SN>
<NAME>crank casing</NAME>
<QTY>1</QTY>
</ITEM>
</ORDER>
IntoElem
移动你的当前主位置到当前子元素位置,然后你就可以在这下面增加一个子元素了。CMarkup在索引中保持了一个当前位置指针,以保证你的源码更加短和更简单,当导航文件时,相同的逻辑位置也会被使用。
CMarkup xml;
xml.SetDoc( csXML );
while ( xml.FindChildElem("ITEM") )
{
xml.IntoElem();
xml.FindChildElem( "SN" );
CString csSN = xml.GetChildData();
xml.FindChildElem( "QTY" );
int nQty = atoi( xml.GetChildData() );
xml.OutOfElem();
}
IntoElem
,查询完之后再调用
OutOfElem
,当你习惯于这种导航类型时,你将知道,检查你的循环时,要确定每个
IntoElem
调用都有一个与之对应的
OutOfElem
调用 。
IntoElem
和
AddElem
来代替
AddChildElem
,函数调用。虽然这意味着更多的调用,但许多人认为这样更直观。
CMarkup xml;
xml.AddElem( "ORDER" );
xml.IntoElem(); // inside ORDER
for ( int nItem=0; nItem<aItems.GetSize(); ++nItem )
{
xml.AddElem( "ITEM" );
xml.IntoElem(); // inside ITEM
xml.AddElem( "SN", aItems[nItem].csSN );
xml.AddElem( "NAME", aItems[nItem].csName );
xml.AddElem( "QTY", aItems[nItem].nQty );
xml.OutOfElem(); // back out to ITEM level
}
xml.AddElem( "SHIPMENT" );
xml.IntoElem(); // inside SHIPMENT
xml.AddElem( "POC" );
xml.SetAttrib( "type", csPOCType );
xml.IntoElem(); // inside POC
xml.AddElem( "NAME", csPOCName );
xml.AddElem( "TEL", csPOCTel );
<ORDER>
<ITEM>
<SN>132487A-J</SN>
<NAME>crank casing</NAME>
<QTY>1</QTY>
</ITEM>
<ITEM>
<SN>4238764-A</SN>
<NAME>bearing</NAME>
<QTY>15</QTY>
</ITEM>
<SHIPMENT>
<POC type="non-emergency">
<NAME>John Smith</NAME>
<TEL>555-1234</TEL>
</POC>
</SHIPMENT>
</ORDER>
FindElem
和
FindChildElem
方法用于到下一个兄弟元素。如果可选的标签名被指定,那么它们将到下一个与标签名相匹配的元素,被发现的元素是当前元素,并且下次调用Find将会到当前位置后的下一个兄弟或下一个匹配兄弟。
IntoElem
进入到ORDER元素,并且用
FindElem("ITEM")
替换
FindChildElem("ITEM")
;其实两种方式都挺好。需要注意的是,在Find方法中指定ITEM元素的标签名,我们会忽略所有其它的兄弟元素,例如SHIPMENT元素。
CMarkup xml;
xml.SetDoc( csXML );
xml.FindElem(); // ORDER element is root
xml.IntoElem(); // inside ORDER
while ( xml.FindElem("ITEM") )
{
xml.FindChildElem( "SN" );
if ( xml.GetChildData() == csFindSN )
break; // found
}
<?xml version="1.0" encoding="ISO-8859-1"?>
,
需要通过用SetDoc或Cmarkup的构造函数来传递。在结尾要包括回车符,这样根结点会显示在下一行。
xml.SetDoc( "<?xml version=""1.0"" encoding=""ISO-8859-1""?>"r"n" );
xml.AddElem( "island", "Curaçao" );
CMarkup类解析xml文件
将CMarkup.cpp和CMarkup.h导入到我们的工程中就可以了。编译可能会出现问题,解决的方法是在CMarkup.cpp的开头加上#include <stdafx.h>,或者关闭预编译也可以。
1、创建一个XML文档
1 CMarkup xml;
2 xml.Load("School.xml");
3 BOOL bFind=TRUE;
4 xml.ResetMainPos();
5
6 while(xml.FindChildElem("Department"))
7 {
8 CString strTagName=_T("");
9 CString strData=_T("");
10 strTagName=xml.GetChildTagName(); //此时节点是父节点
11 strData=xml.GetChildData();
12 TRACE("\n---tagName:%s,Da
13 }
//***********************这样也可以*****************************/
1 CMarkup xml;
2 xml.Load("School.xml");
3 BOOL bFind = TRUE;
4 xml.ResetMainPos();
5
6 while (xml.FindChildElem("Department"))
7 {
8 xml.IntoElem();
9 CString strTagName = _T("");
10 CString strData = _T("");
11 strTagName = xml.GetTagName();
12 strData = xml.GetData();
13 TRACE("\n---tagName:%s,Da
14 xml.OutOfElem();
15 }
//***********************或者这样也可以***************************/
1 CMarkup xml;
2 xml.Load("School.xml");
3 BOOL bFind = TRUE;
4 xml.ResetMainPos();
5 xml.FindElem(); //School
6 xml.IntoElem();
7
8 while (xml.FindElem("Department"))
9 {
10 CString strTagName = _T("");
11 CString strData = _T("");
12 strTagName = xml.GetTagName();
13 strData = xml.GetData();
14 TRACE("\n---tagName:%s,Da
15 }
//***********结果**************
---tagName:Department,Da
---tagName:Department,Da
---tagName:Department,Da
---tagName:Department,Da
3、修改元素
//把Department为”English“改为”Chinese“
1 CMarkup xml;
2 BOOL bLoadXml=FALSE;
3 bLoadXml=xml.Load("School.xml");
4
5 if(bLoadXml)
6 {
7 CString str=_T("");
8 xml.ResetMainPos();
9 xml.FindElem();
10 xml.IntoElem();
11 while(xml.FindElem("Department"))
12 {
13 str=xml.GetData();
14 if(str=="English")
15 {
16 xml.SetData("Chinese");
17 xml.Save("School.xml");
18 break;
19 }
20 }
21 }
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <School>
3 <Department>Automation</Department>
4 <Department>Computer</Department>
5 <Department>Math</Department>
6 <Department>Chinese</Department>
7 </School>
8
对于创建一个XML文档,需要实例化一个CMarkup对象,并调用AddElem创建根元素。在这个位置,如果你调用 AddElem("School") ,文档会简单的装一个空元素<School/>. 然后调用AddChildElem 在根元素的下面创建元素。
1 CMarkup xml;
2 xml.SetDoc("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
3 xml.AddElem("School");
4 xml.IntoElem();
5 xml.AddElem("Department","Automation");
6 xml.AddElem("Department","Computer");
7 xml.AddElem("Department","Math");
8 xml.AddElem("Department","English");
9 xml.OutOfElem();
10 xml.Save("School.xml");
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <School>
3 <Department>Automation</Department>
4 <Department>Computer</Department>
5 <Department>Math</Department>
6 <Department>English</Department>
7 </School>
8
2、浏览特定元素
4、添加
4、1 添加在最后面(用AddElem)
1 CMarkup xml;
2 BOOL bLoadXml=FALSE;
3 bLoadXml=xml.Load("School.xml");
4 if(bLoadXml)
5 {
6 xml.ResetMainPos();
7 xml.FindElem();
8 xml.IntoElem();
9 xml.AddElem("Department","SiQinghua");
10 xml.OutOfElem();
11 xml.Save("School.xml");
12 }
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <School>
3 <Department>Automation</Department>
4 <Department>Computer</Department>
5 <Department>Math</Department>
6 <Department>Chinese</Department>
7 <Department>SiQinghua</Department>
8 </School>
4、2 添加在最前面(用InsertElem)
1 CMarkup xml;
2 BOOL bLoadXml=FALSE;
3 bLoadXml=xml.Load("School.xml");
4 if(bLoadXml)
5 {
6 xml.ResetMainPos();
7 xml.FindElem();
8 xml.IntoElem();
9 xml.AddElem("Department","SiQinghua");
10 xml.OutOfElem();
11 xml.Save("School.xml");
12 }
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <School>
3 <Department>NARI</Department>
4 <Department>Automation</Department>
5 <Department>Computer</Department>
6 <Department>Math</Department>
7 <Department>Chinese</Department>
8 <Department>SiQinghua</Department>
9 </School>
10
5、删除
1 CMarkup xml;
2 BOOL bLoadXml=FALSE;
3 bLoadXml=xml.Load("School.xml");
4 if(bLoadXml)
5 {
6 BOOL bFind=TRUE;
7 xml.ResetMainPos();
8 while(bFind)
9 {
10 bFind=xml.FindChildElem("Department");
11 if(bFind)
12 {
13 CString strData=_T("");
14 strData=xml.GetChildData(); //此时节点还是父节点
15 if("SiQinghua"==strData)
16 {
17 xml.RemoveChildElem();
18 xml.Save("School.xml");
19 break;
20 }
21 }
22 }
23 }
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <School>
3 <Department>NARI</Department>
4 <Department>Automation</Department>
5 <Department>Computer</Department>
6 <Department>Math</Department>
7 <Department>Chinese</Department>
8 </School>
上面的例子都是不带属性的,下面举一个带有属性的例子。
1、生成XML文档
1 CMarkup xml;
2 xml.SetDoc("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
3 xml.AddElem("UserInfo");
4 xml.IntoElem();
5 for(int i=0;i<10;i++)
6 {
7 CString strID=_T("");
8 CString strPwd=_T("");
9
10 srand(UINT(time(NULL)+i)); //产生一个随机数
11 int nLevel=rand()%256;
12
13 strID.Format("UserID%02d",i);
14 strPwd.Format("UserPwd%02d",i);
15
16 xml.AddElem("User");
17 xml.AddAttrib("UserID",strID);
18 xml.AddAttrib("UserPwd",strPwd);
19 xml.AddAttrib("UserLevel",nLevel);
20 }
21 xml.OutOfElem();
22 xml.Save("UserInfo.xml");
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <UserInfo>
3 <User UserID="UserID00" UserPwd="UserPwd00" UserLevel="85"/>
4 <User UserID="UserID01" UserPwd="UserPwd01" UserLevel="88"/>
5 <User UserID="UserID02" UserPwd="UserPwd02" UserLevel="92"/>
6 <User UserID="UserID03" UserPwd="UserPwd03" UserLevel="95"/>
7 <User UserID="UserID04" UserPwd="UserPwd04" UserLevel="98"/>
8 <User UserID="UserID05" UserPwd="UserPwd05" UserLevel="101"/>
9 <User UserID="UserID06" UserPwd="UserPwd06" UserLevel="105"/>
10 <User UserID="UserID07" UserPwd="UserPwd07" UserLevel="108"/>
11 <User UserID="UserID08" UserPwd="UserPwd08" UserLevel="111"/>
12 <User UserID="UserID09" UserPwd="UserPwd09" UserLevel="115"/>
13 </UserInfo>
14
2、查找特定属性
1 CMarkup xml;
2 BOOL bLoadXml=FALSE;
3 BOOL bFind=FALSE;
4 bLoadXml=xml.Load("UserInfo.xml");
5 if(bLoadXml)
6 {
7 CString strID;
8 CString strPwd;
9 xml.ResetMainPos();
10 xml.FindElem(); //UserInfo
11 while(xml.FindChildElem("User"))
12 {
13 strID=xml.GetChildAttrib("UserID");
14 strPwd=xml.GetChildAttrib("UserPwd");
15 TRACE("\n---id:%s,pwd:%s---\n",strID,strPwd);
16 if(strID=="UserID02" && strPwd=="UserPwd02")
17 {
18 bFind=TRUE;
19 break;
20 }
21 }
22 }
23 if(bFind==TRUE)
24 TRACE("\n---find---\n");
25 else
26 TRACE("\n---not find---\n");
3、修改特定属性
1 CMarkup xml;
2 BOOL bFind=FALSE;
3 BOOL bLoadXml=FALSE;
4 bLoadXml=xml.Load("UserInfo.xml");
5 if(bLoadXml)
6 {
7 CString strID;
8 CString strPwd;
9 xml.ResetMainPos();
10 xml.FindElem(); //UserInfo
11 while(xml.FindChildElem("User"))
12 {
13 strID=xml.GetChildAttrib("UserID");
14 strPwd=xml.GetChildAttrib("UserPwd");
15 TRACE("\n--id:%s,pwd:%s--\n",strID,strPwd);
16 if(strID=="UserID02" && strPwd=="UserPwd02")
17 {
18 bFind=TRUE;
19 xml.SetChildAttrib("UserID",strID+CString("Modified"));
20 xml.Save("UserInfo.xml");
21 break;
22 }
23 }
24 }
25 if(bFind==TRUE)
26 TRACE("\n---find---\n");
27 else
28 TRACE("\n---not find---\n");
效果如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <UserInfo>
3 <User UserID="UserID00" UserPwd="UserPwd00" UserLevel="85"/>
4 <User UserID="UserID01" UserPwd="UserPwd01" UserLevel="88"/>
5 <User UserID="UserID02Modified" UserPwd="UserPwd02" UserLevel="92"/>
6 <User UserID="UserID03" UserPwd="UserPwd03" UserLevel="95"/>
7 <User UserID="UserID04" UserPwd="UserPwd04" UserLevel="98"/>
8 <User UserID="UserID05" UserPwd="UserPwd05" UserLevel="101"/>
9 <User UserID="UserID06" UserPwd="UserPwd06" UserLevel="105"/>
10 <User UserID="UserID07" UserPwd="UserPwd07" UserLevel="108"/>
11 <User UserID="UserID08" UserPwd="UserPwd08" UserLevel="111"/>
12 <User UserID="UserID09" UserPwd="UserPwd09" UserLevel="115"/>
13 </UserInfo>
CMarkup免费版的一些扩展
最近,在工作中需要分析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是一个结构体,它的内容如下:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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是一个结构体,它存储了结点的信息:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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计)
其它成员有待研究
举例说明如下:
假设上面的内容就是我们的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就容易多了。
CMarkup官方教程
CMarkUp利用简介.
最近正在琢磨C++下的XML分析工具CMarkup。初次和XML相遇是基于C#对XML的垄断。C#的XmlDocument和XmlNode给我印象之深,让我至今都无法淡忘。目前想在C++下挖掘XML的壮大,收获却觉察建房子你除非必需大约的创立材料外,还必需些而外的工具。不像C#那样,曾经打成包供你直接利用了。好在有懂得CMarkup这个小型XML的分析器,可感受我所用。俗语说:磨刀不误砍柴工。我目前就来磨下刀。
1、初始化
Load 导入一个XML文件到CMarkup的对象中,并对它举行解析。相仿C#的Load。
SetDoc 从字符串中导入XML数据,并对它解析。相仿C#的LoadXml。
2、输出
Save 将XML数据写入文件中。相仿C#的Save。
GetDoc 将全副XML数据文档作为字符串归来。
3、改换目前位置
FindElem 定位到下一个元素,可能和一个标签名或路径相称。
FindChildElem 定位到下一个子元素,相称元素名或路径。
FindPrevElem 定位前一个元素,可能和一个标签名或路径相称。
FindPrevChildElem 定位前一个子元素,可能相称标签名。
FindNode 定位下一个节点,可能和节点种类相称。
IntoElem 进去目前主位置的下一级,目前的位置变为父位置。
OutOfElem 使目前父位置变成目前位置。
ResetPos 复位目前位置为文档起始位置。
ResetMainPos 将目前主位置复位为第一个兄弟位置之前。
ResetChildPos 复位目前子位置到第一个子位置之前。
4、文档新增
AddElem 在目前主位置元素或最后兄弟位置尔后添置一个元素。
InsertElem 在目前主位置元素或第一个兄弟位置之前插入一个元素。
AddChildElem 在目前子位置元素或最后一个子位置尔后添置一个元素。
InsertChileElem 在目前子位置元素或低一个子位置之前插入一个元素。
AddSubDoc 在目前主位置元素或最后一个兄弟位置尔后添置一个子文档。
InsertSubDoc 在目前主位置元素或第一个兄弟位置之前插入一个子文档。
AddChildSubDoc 在目前子位置元素或最后一个子位置尔后添置子文档。
InsertChildSubDoc 在目前子位置元素或第一个子位置之前插入一个子文档。
AddNode 在目前节点尔后或父元素内容末路添置一个节点。
InsertNode 在目前节点之前或父元素内容开始插入一个节点。
5、文档中剔除
RemoveElem 剔除目前包括子元素的主位置元素
RemoveChildElem 剔除包括目前子元素及其子元素
RemoveNode 剔除目前节点
RemoveAttrib 剔除目前位置元素翔实的属性
RemoveChildAttrib 剔除目前子位置元素的某个翔实属性
6、获得值
GetData 取贴切前主位置元素或节点的字符串值
GetChildData 取贴切前子位置元素的字符串值
GetElemContent 取贴切前主位置元素包括其子元素的符号内容字符串值
GetSubDoc 取贴切前主位置元素包括其子元素的文档片断符号字符串值
GetChildSubDoc 取贴切前子位置元素包括其子元素的文档片断符号字符串值
GetAttrib 获得主位置元素(或正在举行的号召的)某一翔实属性字符串值
GetChildAttrib 获得子位置某一特定属性的字符串值
GetTagName 获得主位置元素(或正在举行的号召的)标签名目
GetChildTagName 获得子位置元素的标签名目
FindGetData 定位到相称某一翔实路径的下一个元素并归来字符串值
7、设置值
SetData 设置目前主位置元素或节点的值
SetChildData 设置目前子位置元素的值
SetElemContent 设置目前主位置元素的符号内容
SetAttrib 设置目前主位置元素(或正在举行的号召的)某一翔实属性的值
SetChildAttrib 设置目前子位置元素某一翔实属性的值
FindSetData 定位相称某一翔实路径的下一个元素并设置其值
8、获得其他消息
GetAttribName 当过目前位置元素属性的翔实索引获得属性名目
GetNodeType 取贴切前节点的节点种类
GetElemLevel 取贴切前主位置的级数
GetElemFlags 取贴切前主位置元素的符号
SetElemFlags 设置目前主位置元素的符号
GetOffsets 获得在目前主位置偏移的文档文本
GetAttribOffsets 获得在目前主位置特定属性低廉的文档文本
9、保留位相消息
SavePos 在hash map中利用可选字符串名目保留目前位置
RestorePos 定位到穿越SavePos保留的位置
SetMapSize 设置SavePos和RestorePos利用的hash map大小
GetElemIndex 取贴切前主位置元素美容索引值
GotoElemIndex 设置目前主位置元素为给定的美容索引值
GetChildElemIndex 取贴切前子位置元素的美容索引值
GotoChildElemIndex 设置目前子位置元素为给定的美容索引值
GetParentElemIndex 获贴切前父位置元素的美容索引值
GotoParentElemIndex 设置目前父位置元素为给定的美容索引值
GetElemPath 获得表示主位置元素绝对路径的字符串
GetChildElemPath 获得表示子位置元素的绝对路径的字符串
GetParentElemPath 获得表示父位置元素的绝对路径的字符串
10、文档事态
IsWellFormed 判定文档是否有单一根元素和稳妥地包括元素
GetError 从最后的解析中归来讹谬(消息)字符串
GetDocFlags 归来文档符号
SetDocFlags 设置文档符号
GetDocElemCount 归来文档中元素的个数
11、静态的实用函数
ReadTextFile 读一个文本文件转成字符串
WirteTextFile 写字符串到文本文件中
GetDeclareEncoding 从XML声明中获得编码的名字
EscapeText 归来符号中某一字符的编码
UnescapeText 归来字符串划算某一特定字符解码
UTF8ToA 将UTF-8字符转成非Unicode(如ANSI)字符
AToUTF8 将非Unicode(如ANSI)字符转成UTF-8字符
UTF16T08 将UTF-16字符转成UTF-8
UTF8To16 将UTF-8字符转成UTF-16
EncodeBase64 将二进制数据译成Base64字符串
DecodeBase64 将Base64字符译成二进制数据
自此,CMarkup的措施解释我曾经翻译告终。有许多都是按照自己的会意或纯按字面含义翻译的。确定还是会意不够准确地。后面的文章中,我会对每一个措施的代码举行一些容易分析,重要是给自己做技巧聚集用。迎接大家点拨!String s = new String ("Text here");
(一) 先讲一下XML中的物殊字符,手动填写时注意一下。
字符 字符实体
& &或&#38;
' '或'
> >或>
< <或&<
" "或"
(二) CMarkup类的源代码。
这是目前的最新版本;
这是官网示例文件,取出里面的Markup.cpp和Markup.h,导入你的工程里面,CMarkup类就可以用了;
下载地址:http://www.firstobject.com/Markup112.zip 2009年9月3日官网最新版
如果下载不了,可以到官网去下载 http://www.firstobject.com/dn_markup.htm
(三) 创建一个XML文档。
CMarkup xml;
xml.AddElem( "ORDER" );
xml.AddChildElem( "ITEM" );
xml.IntoElem();
xml.AddChildElem( "SN", "132487A-J" );
xml.AddChildElem( "NAME", "crank casing" );
xml.AddChildElem( "QTY", "1" );
xml.Save("c:\\UserInfo.xml");
效果如下:
<ORDER><ITEM><SN>132487A-J</SN><NAME>crank casing</NAME><QTY>1</QTY></ITEM></ORDER>
(四) 浏览特定元素
CMarkup xml;xml.Load("UserInfo.xml"); while ( xml.FindChildElem("ITEM") ){ xml.IntoElem(); xml.FindChildElem( "SN" ); CString csSN = xml.GetChildData(); xml.FindChildElem( "QTY" ); int nQty = atoi( xml.GetChildData() ); xml.OutOfElem();}
(五)增加元素和属性
添加在最后面,使用的是AddElem;添加在最前面,使用InsertElem。
CMarkup xml;
xml.Load("c:\\UserInfo.xml");xml.AddElem( "ORDER" );xml.IntoElem(); // 进入 ORDER xml.AddElem( "ITEM" ); xml.IntoElem(); // 进入 ITEM xml.AddElem( "SN", "4238764-A" ); //添加元素 xml.AddElem( "NAME", "bearing" );//添加元素 xml.AddElem( "QTY", "15" );//添加元素 xml.OutOfElem(); // 退出 ITEM
xml.AddElem( "SHIPMENT" );xml.IntoElem(); // 进入 SHIPMENTxml.AddElem( "POC" );//添加元素xml.SetAttrib( "type", "non-emergency");//添加属性xml.IntoElem(); // 进入 POCxml.AddElem( "NAME", "John Smith");//添加元素xml.AddElem( "TEL", "555-1234");//添加元素xml.Save("c:\\UserInfo.xml");
效果如下:
<ORDER><ITEM><SN>132487A-J</SN><NAME>crank casing</NAME><QTY>1</QTY></ITEM><ITEM><SN>4238764-A</SN><NAME>bearing</NAME><QTY>15</QTY></ITEM><SHIPMENT><POCtype="non-emergency"><NAME>John Smith</NAME><TEL>555-1234</TEL></POC></SHIPMENT></ORDER>
(六) 修改元素和属性
如将POC中的属性type改成:change;
元素TEL改成:123456789
CMarkup xml;
if (xml.Load("UserInfo.xml"))
{
CString strUserID = _T("");
xml.ResetMainPos();
if (xml.FindChildElem("SHIPMENT"))
{
xml.IntoElem();
if (xml.FindChildElem("POC"))
{
xml.IntoElem();
CString str_type=xml.GetAttrib("type");
MessageBox(str_type);
xml.SetAttrib("type","change");
strUserID = xml.GetData();
if (xml.FindChildElem("TEL"))
{
xml.IntoElem();
xml.SetData("123456789");
xml.Save("UserInfo.xml");
return;
}
}
}
}
(七)删除元素:
删除SN=132487A-J的项目。
CMarkup xml;
if (xml.Load("UserInfo.xml"))
{
CString strUserID = _T("");
xml.ResetMainPos();
if (xml.FindChildElem("ITEM"))
{
xml.IntoElem();
CString str_sn;
xml.FindChildElem("SN");
str_sn=xml.GetChildData();
if(str_sn=="132487A-J")
{
xml.RemoveElem();
xml.Save("UserInfo.xml");
}
}
}