收集的一些关于CMarkUp介绍

来源:互联网 发布:淘宝网箱包类 编辑:程序博客网 时间:2024/05/01 19:50
下面是CMarkup的类成员函数列表。这些函数的设计都是基于源EDOM的。带阴影的函数只存在于CMarkup的Developer版本中。(译注:所谓Developer版本就是收费的,我们一般使用他的Evaluation版本,其实就是阉割版o(∩_∩)o ,不过已经够了,因此下面的翻译中带阴影的函数我就不列出来了,可以自己去原文看。)

     初始化
      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字符串

 

 

创建一个新的XML文档,分析修改现存的XML文档,所有的这些都中可以从一个利用MFC或STL字符串所实现的一个简单类的方法中得到。关于CMarkup,你可以运行Zip文件右边的例子,如果你愿意,你可以通过看源码,几分钟把它加入到你自己的应用中。
特征
Cmarkup是依据EDOM的,这是这个简单XML分析的关键。EDOM是操作XML元素、属性和数据的简明方法集。当你不需要复杂的XML特性时,它避免你读大量的DOM和SAX文档。
如果你希望使用微软的MSXML,CMarkup工程中CmarkupMSXML类全面的演示了通过EDOM来使用MSXML,并且它是以C++ COM语法开始。
下载包(看上面zip文件的链接)中包含了测试对话框工程的源码、Cmarkup类的所有测试和示例、以及编译选项。关于用在商业用途中的详细说明请看文章底部的在Licensing中的注意事项。       
下面列出了CMarkup的特征:
独立:不需要任何外部的XML组件。
小:编译到你的工程只是很小的一个类,并且对于文档只维持了一个字符串,以及一个总计小于字符串内存大小的索引数组。
快:分析器在相当快的建立索引数组。
简单:EDOM方法使创建、导航和修改XML无比的简单。
MSXML:CMarkupMSXML类用EDOM方法包装了微软的XML服务。MSXML编译选项用来演示这个类。
UNICODE(统一字符编码标准):对于WindowsNT和WindowsCE平台能够被编译成UNICODE,在WindowsNT UNICODE下,XML文档是流到UTF-8文件中,但是内部用宽字符。
UTF-8:对于UTF-8文件,这接受和返回UTF-8字符串(确保_MBCS没有被定义)
MBCS:对于双字节数据(定义_MBCS),它不与UTF-8兼容.
STL:CMarkupSTL类完全没有使用MFC,它的演示要使用STL编译选项。
 
每天数据的XML
 我们经常在一个文件里需要保存或传递信息,或从计算机A 发送一个信息块到计算机B。总是有这样一个问题出现:我要怎样安排这些数据的格式?出现XML之前,你可能要考虑“env”类型,例如PATH=C:"WIN95; “ini”类型(一些部分的组合),逗号限制或其它一些限制、或者是固定了字符串的长度。现在XML就是被确定的这些问题的答案,但是某些时候,程序员很气馁,他们需要一些便于帮助分析和格式尖括号所有这些的解决XML的复杂性。对于最低限度读XML标签匹配规则,我建议阅读在CcodeProject站点的“Beginning XML - Chapter 2: Well-Formed XML
XML 更好是因为它的灵活和自然的等级,加上它广泛的应用。虽然XML比限定格式用了更多的字符,如果需要的话它可以良好的向下压缩。当你需要扩展你文档信息类型时,XML的灵活性得到了体现,不需要要求信息的每个消费者重写逻辑过程。你能够保持旧的信息标识,并且制定用相同的方式增加新属性和元素。
 
使用CMarkup
Cmarkup 是基于“压缩”文档对象模型(EDOM : "Encapsulated" Document Object Model,),这是这个简单XML处理器的关键。它的一套XML处理方法和产生的效果与DOM(Document Object Model)是一样的。但是整个DOM有无数的对象类型,而EDOM只定义了一个对象:XML文档,EDOM回到了XML原始的吸引力—简单。关于方法的完整文档,请看EDOM Specification.
CmarkUp 封装了XML文档文本、结构和当前位置。它提供了增加元素、导航和得到元素属性和数据的所有方法以。在文档中操作被执行的地方取决于当前位置和当前孩子位置。当前位置允许你增加一个元素到文档中的这个位置,而不需要明确指出增加对象到文档的这点上,在CMarkup的有效生命周期里,对象一直保持着一个用来描述文档的字符串,当你调用GetDoc.可以得到它。 
查看free firstobject XML editor的源码,这是用CMarkup创建、导航你自己的XML文档。
创建一个XML文档
对于创建一个XML文档,需要实例化一个CMarkup对象,并调用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();
这些代码产生了下面的XML,这个根结点是ORDER元素;注意它的开始标签<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在索引中保持了一个当前位置指针,以保证你的源码更加短和更简单,当导航文件时,相同的逻辑位置也会被使用。
导航XML文档
上面的例子所创建的XML字符串,用SetDoc方法加入到CMarkup对象中能够被解析,你也可以引导它正确的进入被创建的同一个CMarkup对象中,如果你要设置当前位置到文档的开始时,需要调用ResetPos.
在下面的例子中,从csXML字符串生成CMarkup对象后,我们循环ORDER元素下的所有ITEM元素,并得到每个项目的序号和数量。
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 调用 。
增加元素和属性
上面创建文档的例子中仅创建了一个ITEM元素,现在这个例子是创建多个项目,从前一个内容加裁后,再增加数据源,加上SHIPMENT信息元素中有一个属性,这段代码也演示了你能调用调用IntoElemAddElem来代替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 );
这段代码产生了下面的XML,根元素ORDER包含两个ITEM元素和一个SHIPMENT元素,ITEM元素全都包含SN、NAME、和QTY元素,SHIPMENT元素包含一个带有属性类型的POC元素,和NAME及TEL子元素。

<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>

查找元素
FindElemFindChildElem方法用于到下一个兄弟元素。如果可选的标签名被指定,那么它们将到下一个与标签名相匹配的元素,被发现的元素是当前元素,并且下次调用Find将会到当前位置后的下一个兄弟或下一个匹配兄弟。
当你无法判断元素的索引时,在调用两个Find方法之间,一定要复位当前位置。看上面的例子中ITEM元素,如果是别的人创建的XML文件,你不能确定SN元素在QTY元素之前,那么在查找QTY元素之前就要调用ResetChildPos();
对于用一个特定的序号去查找元素,你需要完全循环ITEM元素,并比较SN元素的数据和你正在搜索的序号。这个例子不同于先前导航的例子,它调用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
}
编码
ASCII编码引用了我们所依靠的字符码128以下的字符,如用英语编程。如果你只使用ASCII码,很方便,UTF-8编程与你拉公共ASCII集相同。
如果你所使用的字符集不在Unicode编码集(UTF-8,UTF-16,UCS-2)中,那么出于交互性以及在IE中很好的显示,你真的需要在XML声明中进行描述。像ISO-8859-1(西欧)字符集指定字符值在一个比特且在128到255之间。以便每个字符仍然使用一个比特。Windows双字节字符集像GB2312,Shift_JIS和EUC-KR,每个字符都是用一个或两个字节,对于这些Windows字符集,在你的预处理中需要定义 _MBCS ,并要确定用户的操作系统设置到合适的编码页。
关于用一个XML描述的XML文档前缀,像<?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" );
测试对框
Markup.exe 是一Cmarkup的测试程序,这是一个VC6下的MFC工程。当它开始时,工程在OnTest函数里运行诊断程序,在选择了特定的编译选项下测试 Cmarkup.,你可以一步一步的调试OnTest函数,会看到怎样用Cmarkup的一些例子,用Open和Parse函数测试一个文件。
在下面的插图里,显示的编译版本是“CMarkup 7.0 Unicode”,这意味着Cmarkup类是用在_UNICODE定义下编译的。成功的运行了RunTest,分析错误在 Charsets_err.xml文件中被遇到,文件被加载,文件原是1500比特转换到1033Unicode宽字符(例如2066字节),但是它遇到了一个结束标签与起始标签不对应的错误 。
这个测试对话框保存着最后一个被分析文件和对话框的屏幕位置信息,这些都被注册表中的HKEY_CURRENT_USER/ Software/ First Objective Software/ Markup/ Settings.键下。

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,Data:%s--\n",strTagName,strData);

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,Data:%s--\n",strTagName,strData);

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,Data:%s--\n",strTagName,strData);

15      }

//***********结果**************

      ---tagName:Department,Data:Automation--

---tagName:Department,Data:Computer--

---tagName:Department,Data:Math--

---tagName:Department,Data:English--

3、修改元素

//把Department为”English“改为”Chinese“

1      CMarkup xml;

2      BOOL bLoadXml=FALSE;

3      bLoadXml=xml.Load("School.xml");

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("");

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计)

其它成员有待研究

举例说明如下:

<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就容易多了。

CMarkup官方教程

CMarkup Methods

This is the master list of CMarkup class methods. The CMarkup methods are based on the originalEDOM design. Theshaded methods are only available in theDeveloper Version of CMarkup.

Initialization

LoadPopulates the CMarkup object from a file and parses itSetDocPopulates the CMarkup object from a string and parses it

Output

SaveWrites the document to fileGetDocReturns the whole document as a markup stringGetDocFormattedReturns the formatted markup string of the whole document

File mode

OpenOpens file, initiating file mode for read or write (and append is a special case of write mode)CloseCloses file and ends file modeFlushFor file write mode, this flushes any partial document in memory (up to the closing tags) and the file stream itself

Changing the current position

FindElemLocates next element, optionally matching tag name or pathFindChildElemLocates next child element matching tag name or pathFindPrevElemLocates previous element, optionally matching tag nameFindPrevChildElemLocates previous child element, optionally matching tag nameFindNodeLocates next node, optionally matching node type(s)IntoElemGo "into" current main position element such that it becomes the current parent positionOutOfElemMakes the current parent position into the current main positionResetPosResets the current position to the start of the documentResetMainPosResets the current main position to before the first siblingResetChildPosResets the current child position to before the first child

Adding to the Document

AddElemAdds an element after the current main position element or last siblingInsertElemInserts an element before the current main position element or first siblingAddChildElemAdds an element after the current child position element or last childInsertChildElemInserts an element before the current child position element or first childAddSubDocAdds a subdocument after the current main position element or last siblingInsertSubDocInserts a subdocument before the current main position element or first siblingAddChildSubDocAdds a subdocument after the current child position element or last childInsertChildSubDocInserts a subdocument before the current child position element or first childAddNodeAdds a node after the current node or at the end of the parent element contentInsertNodeinserts a node before the current node or at the beginning of the parent element content

Removing from the Document

RemoveElemRemoves the current main position element including child elementsRemoveChildElemRemoves the current child position element including its child elementsRemoveNodeRemoves the current nodeRemoveAttribRemoves the specified attribute from the current main position elementRemoveChildAttribRemoves the specified attribute from the current child position element

Getting Values

GetDataReturns the string value of the current main position element or nodeGetChildDataReturns the string value of the current child position elementGetElemContentReturns the string markup content of the current main position element including child elementsGetSubDocReturns the subdocument markup string of the current main position element including child elementsGetChildSubDocReturns the subdocument markup string of the current child position element including child elementsGetAttribReturns the string value of the specified attribute of the main position element (or processing instruction)GetChildAttribReturns the string value of the specified attribute of the child position elementHasAttribReturns true if the specified attribute exists in the main position element (or processing instruction)HasChildAttribReturns true if the specified attribute exists in the child position elementGetTagNameReturns the tag name of the main position element (or processing instruction)GetChildTagNameReturns the tag name of the child position elementFindGetDataLocates the next element matching the specified path and returns the string value

Setting Values

SetDataSets the value of the current main position element or nodeSetChildDataSets the value of the current child position elementSetElemContentSets the markup content of the current main position elementSetAttribSets the value of the specified attribute of the current main position element (or processing instruction)SetChildAttribSets the value of the specified attribute of the current child position elementFindSetDataLocates the next element matching the specified path and sets the value

Other Info

GetAttribNameReturns the name of attribute specified by number for the current main position elementGetNodeTypeReturns the node type of the current nodeGetElemLevelReturns the level of the current main positionGetElemFlagsReturns the current main position element's flagsSetElemFlagsSets the current main position element's flagsGetOffsetsObtains the document text offsets of the current main positionGetAttribOffsetsObtains the document text offsets of the specified attribute in the current main position

Remembering positions

SavePosSaves the current position with an optional string name using a hash mapRestorePosGoes to the position saved with SavePosSetMapSizeSets the size of a map for use with the SavePos andRestorePos methodsGetElemIndexReturns the integer index of the current main position elementGotoElemIndexSets the current main position element to that of the given integer indexGetChildElemIndexReturns the integer index of the current child position elementGotoChildElemIndexSets the current child position element to that of the given integer indexGetParentElemIndexReturns the integer index of the current parent position elementGotoParentElemIndexSets the current parent position element to that of the given integer indexGetElemPathReturns a string representing the absolute path of the main position elementGetChildElemPathReturns a string representing the absolute path of the child position elementGetParentElemPathReturns a string representing the absolute path of the parent position element

Document Status

IsWellFormedDetermines if document has a single root element and properly contained elementsGetResultReturns result markup from last parse or file operationGetErrorReturns English error/result synopsis string from last parse or file operationGetDocFlagsReturns the document flagsSetDocFlagsSets the document flagsGetDocElemCountReturns the number of elements in the document

Static Utility Functions

ReadTextFileReads a text file into a stringWriteTextFileWrites a string to a text fileGetDeclaredEncodingReturns the encoding name as a string from the XML declarationEscapeTextReturns the string with special characters encoded for markupUnescapeTextReturns the string with special characters unencoded for a string valueUTF8ToAConverts a UTF-8 string to a non-Unicode ("ANSI") stringAToUTF8Converts a non-Unicode ("ANSI") string to UTF-8UTF16To8Converts a UTF-16 string to UTF-8UTF8To16Converts a UTF-8 string to UTF-16EncodeBase64Encodes a binary data buffer to a Base64 stringDecodeBase64Encodes a Base64 string to a binary data buffer

Fast start to XML in C++

Enough bull. You want to create XML or read and find things in XML. All you need to know about CMarkup is that it is just one object per XML document (for the API design concept seeEDOM). And by the way thefree firstobject XML Editor generates C++ source code for creating and navigating your own XML documents with CMarkup.

Creating an XML Document

To create an XML document, instantiate a CMarkup object and call AddElem to create the root element. At this point, if you called AddElem("ORDER") your document would simply contain the empty ORDER element<ORDER/>. Then callAddChildElem to create elements under the root element (i.e. "inside" the root element, hierarchically speaking). The following example code creates an XML document and retrieves it into a CString:

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();

This code generates the following XML. The root is the ORDER element; notice that its start tag<ORDER> is at the beginning and end tag</ORDER> is at the bottom. When an element is under (i.e. inside or contained by) a parent element, the parent's start tag is before it and the parent's end tag is after it. The ORDER element contains one ITEM element. That ITEM element contains 3 child elements: SN, NAME, and QTY.

<ORDER><ITEM><SN>132487A-J</SN><NAME>crank casing</NAME><QTY>1</QTY></ITEM></ORDER>

As shown in the example, you can create elements under a child element by callingIntoElem to move your current main position to where the current child position is so you can begin adding under that one. CMarkup maintains a current position in order to keep your source code shorter and simpler. This same position logic is used when navigating a document.

Navigating an XML Document

The XML string created in the above example can be parsed into a CMarkup object with theSetDoc method. You can also navigate it right inside the same CMarkup object where it was created; just callResetPos if you want to go back to the beginning of the document.

In the following example, after populating the CMarkup object from the csXML string, we loop through all ITEM elements under the ORDER element and get the serial number and quantity of each item:

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();}

For each item we find, we call IntoElem before interrogating its child elements, and thenOutOfElem afterwards. As you get accustomed to this type of navigation you will know to check in your loops to make sure there is a correspondingOutOfElem call for everyIntoElem call.

Adding Elements and Attributes

The above example for creating a document only created one ITEM element. Here is an example that creates multiple items loaded from a previously populated data source, plus a SHIPMENT information element in which one of the elements has an attribute. This code also demonstrates that instead of calling AddChildElem, you can callIntoElem andAddElem. It means more calls, but some people find this more intuitive.

CMarkup xml;xml.AddElem( "ORDER" );xml.IntoElem(); // inside ORDERfor ( 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 SHIPMENTxml.AddElem( "POC" );xml.SetAttrib( "type", csPOCType );xml.IntoElem(); // inside POCxml.AddElem( "NAME", csPOCName );xml.AddElem( "TEL", csPOCTel );

This code generates the following XML. The root ORDER element contains 2 ITEM elements and a SHIPMENT element. The ITEM elements both contain SN, NAME and QTY elements. The SHIPMENT element contains a POC element which has a type attribute, and NAME and TEL child elements.

<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>

Finding Elements

The FindElem and FindChildElem methods go to thenext sibling element. If the optional tag name argument is specified, then they go to the next element with a matching tag name. The element that is found becomes the current element, and the next call to Find will go to the next sibling or matching siblingafter that current position.

When you cannot assume the order of the elements, you must reset the position in between calling the Find method. Looking at the ITEM element in the above example, if someone else is creating the XML and you cannot assume the SN element is before the QTY element, then call ResetChildPos before finding the QTY element.

To find the item with a particular serial number, you can loop through the ITEM elements and compare the SN element data to the serial number you are searching for. This example differs from the original navigation example by callingIntoElem to go into the ORDER element and useFindElem("ITEM") instead ofFindChildElem("ITEM"); either way is fine. And notice that by specifying the "ITEM" element tag name in the Find method we ignore all other sibling elements such as the SHIPMENT element.

CMarkup xml;xml.SetDoc( csXML );xml.FindElem(); // ORDER element is rootxml.IntoElem(); // inside ORDERwhile ( xml.FindElem("ITEM") ){    xml.FindChildElem( "SN" );    if ( xml.GetChildData() == csFindSN )        break; // found}

You are NOT on your own

This site has all kinds of examples of doing various XML operations. CMarkup has been widely used for many years. Of course it doesn't do everything, but almost every purpose has at least been discussed. Don't hesitate to ask if you have questions. A good place to go next is the CMarkup Methods.

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");

VC解析XML--使用CMarkup类解析XML

(一) 先讲一下XML中的物殊字符,手动填写时注意一下。

字符                   字符实体
&                       &amp;或&#38;#38;
'                       &apos;或&#39;
>                       &gt;或&#62;
<                       &lt;或&#38;&#60;
"                        &quot;或&#34;

(二) 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");
    }
   }
}