void CXmlTestDlg::OnGet()
{// TODO: Add your control notification handler code here
CMarkup xml;
if( !xml.Load("f:\\he.xml") )
MessageBox("读取文件失败");
xml.ResetPos();
xml.FindElem();
CString tag = xml.GetTagName();
HTREEITEM hRoot = m_tree.InsertItem(tag);
HTREEITEM hC = m_tree.InsertItem("City",hRoot);
xml.IntoElem();
while(xml.FindElem())
{
CString strTag = xml.GetData();
m_tree.InsertItem(strTag,hC);
}
}
下面是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字符串
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" );
