1、使用条件
C++ Builder对于XML处理主要封装在TXMLDocument组件中。该控件在Internet组中,图标为标识有XML的文档式样。如果没有该控件的话,你需要安装。TXMLDocument不是C++ Builder缺省安装的包,需要自己添加安装包。如果在C++ Builder目录的Bin目录下存在dclnet60.bpl文件,就直接安装就是,否则需要修改安装,以安装该组件包。
2、使用
①.基本操作
a.使用控件方式加载XML文件:
//加载XML文件
OpenDialog1->Filter = "XML(程序配置文件)|*.xml";
if (!OpenDialog1->Execute())
{
return;
}
XMLDoc->LoadFromFile(OpenDialog1->FileName);
_di_IXMLNode node = XMLDoc->DocumentElement;
if (node == NULL)
{
return;
}
//加载XML文件
OpenDialog1->Filter = "XML(程序配置文件)|*.xml";
if (!OpenDialog1->Execute())
{
return;
}
XMLDoc->LoadFromFile(OpenDialog1->FileName);
_di_IXMLNode node = XMLDoc->DocumentElement;
if (node == NULL)
{
ShowMessage("不是合法的程序配置文件XML文件格式。");
return;
}
b.使用控件方式保存XML文件:
SaveDialog1->FileName = FDevTypeName + ".xml";
SaveDialog1->Filter = "XML(程序配置文件)|*.xml";
if (SaveDialog1->Execute())
{
XMLDoc->Active=true;
XMLDoc->Version = "1.0";
XMLDoc->Encoding = "GB2312";
XMLDoc->Options << doNodeAutoIndent;
//建立文档主元素
XMLDoc->DocumentElement = XMLDoc->CreateElement("Config", "");
XMLDoc->DocumentElement->SetAttribute("DevType", FDevTypeName);
//从UI更新XML数据
UpdateXMLDataFromUI(XMLDoc->DocumentElement);
//格式化XML
XMLDoc->LoadFromXML(formatXMLDoc(XMLDoc, 1));
//保存XML文件
XMLDoc->SaveToFile(SaveDialog1->FileName);
ShowMessage("保存配置"+ SaveDialog1->FileName + "文件成功");
}
SaveDialog1->FileName = FDevTypeName + ".xml";
SaveDialog1->Filter = "XML(程序配置文件)|*.xml";
if (SaveDialog1->Execute())
{
XMLDoc->Active=true;
XMLDoc->Version = "1.0";
XMLDoc->Encoding = "GB2312";
XMLDoc->Options << doNodeAutoIndent;
//建立文档主元素
XMLDoc->DocumentElement = XMLDoc->CreateElement("Config", "");
XMLDoc->DocumentElement->SetAttribute("DevType", FDevTypeName);
//从UI更新XML数据
UpdateXMLDataFromUI(XMLDoc->DocumentElement);
//格式化XML
XMLDoc->LoadFromXML(formatXMLDoc(XMLDoc, 1));
//保存XML文件
XMLDoc->SaveToFile(SaveDialog1->FileName);
ShowMessage("保存配置"+ SaveDialog1->FileName + "文件成功");
}
②.读
a.读取节点数据
AnsiString GetNodeData(_di_IXMLNode panode,
AnsiString nodename, AnsiString defaultvalue)
{
//取得子节点列表
_di_IXMLNodeList nodes = panode->ChildNodes;
//从子节点列表查找节点
_di_IXMLNode node = nodes->FindNode(nodename);
if (node == NULL)
{
return defaultvalue;
}
//从节点取得数据
return node->GetText();
}
AnsiString GetNodeData(_di_IXMLNode panode,
AnsiString nodename, AnsiString defaultvalue)
{
//取得子节点列表
_di_IXMLNodeList nodes = panode->ChildNodes;
//从子节点列表查找节点
_di_IXMLNode node = nodes->FindNode(nodename);
if (node == NULL)
{
return defaultvalue;
}
//从节点取得数据
return node->GetText();
}
b.读取节点属性
//在格式描述XML文件中定位列描述
nodename = "grid";
_di_IXMLNode uinode = XMLUI->DocumentElement;
_di_IXMLNodeList uinodelst = uinode->ChildNodes;
uinode = uinodelst->FindNode(nodename);
uinodelst = uinode->ChildNodes;
for (jdx = 0; jdx < uinodelst->Count; jdx++)
{
//取得当前列在表格中的位置
colname = uinodelst->Nodes[jdx]->GetText();
//设置列头
colheader = colname + "(" + uinodelst->Nodes[jdx]->GetAttribute("length") ;
//根据类型设置表格列类型,用于编辑
//取得节点属性示例
if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Hex"))
{
colheader += ", Hex";
}
else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("DevType"))
{
}else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Baud"))
{
}else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Integer"))
{
colheader += ", Dec";
}else
{
colheader += ", Dec";
}
colheader += ")";
//...(省略)
}//~for(jdx...
//在格式描述XML文件中定位列描述
nodename = "grid";
_di_IXMLNode uinode = XMLUI->DocumentElement;
_di_IXMLNodeList uinodelst = uinode->ChildNodes;
uinode = uinodelst->FindNode(nodename);
uinodelst = uinode->ChildNodes;
for (jdx = 0; jdx < uinodelst->Count; jdx++)
{
//取得当前列在表格中的位置
colname = uinodelst->Nodes[jdx]->GetText();
//设置列头
colheader = colname + "(" + uinodelst->Nodes[jdx]->GetAttribute("length") ;
//根据类型设置表格列类型,用于编辑
//取得节点属性示例
if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Hex")){
colheader += ", Hex";
}else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("DevType")){
}else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Baud")){
}else if (AnsiString(uinodelst->Nodes[jdx]->GetAttribute("type")) == AnsiString("Integer")){
colheader += ", Dec";
}else{
colheader += ", Dec";
}
colheader += ")";
//...(省略)
}//~for(jdx...
2.3 写
以下代码演示了如果添加子节点,以及设置属性,写XML文件在第1节点有所描述。
void UpdateNodeData(_di_IXMLNode panode,AnsiString nodename, AnsiString value, AnsiString friendlyname)
{
_di_IXMLNodeList nodes = panode->ChildNodes;
_di_IXMLNode node = nodes->FindNode(nodename);
if (node == NULL){
//添加子节点
node = panode->AddChild(nodename);
//设置属性
node->SetAttribute("FriendlyName", friendlyname);
}
//改变节点数据
node->SetText(value);
}
void UpdateNodeData(_di_IXMLNode panode,AnsiString nodename, AnsiString value, AnsiString friendlyname)
{
_di_IXMLNodeList nodes = panode->ChildNodes;
_di_IXMLNode node = nodes->FindNode(nodename);
if (node == NULL){
//添加子节点
node = panode->AddChild(nodename);
//设置属性
node->SetAttribute("FriendlyName", friendlyname);
}
//改变节点数据
node->SetText(value);
}
2.4 格式化XML
以上代码为格式化XML,调用方式在写XML在2.1.2节中有描述。使用该组件的缩进方式直接
通过写入节点方式并不能得到格式化文档,当加载一个文件时可以自动格式化。一种简单的
格式化方式就是先保存好文件再读取一次,再保存就可以得到格式化的文档。
//声明:该代码源于网络,并做了些修改
AnsiString formatXMLDoc(TXMLDocument* doc, int indent)
{
AnsiString sRes;
int i;
sRes = "<?xml version=/"" + doc->Version + "/" encoding=/"" + doc->Encoding + "/"?>/r/n";
sRes += "<" + doc->DocumentElement->NodeName;
for (i = 0; i < doc->DocumentElement->AttributeNodes->Count; i++)
{
sRes += " " + doc->DocumentElement->AttributeNodes->Nodes[i]->NodeName
+ "=/"" + doc->DocumentElement->AttributeNodes->Nodes[i]->NodeValue + "/"";
}
sRes += ">/r/n";
for (i = 0; i < doc->DocumentElement->ChildNodes->Count; ++i){
sRes += formatXMLNode(doc->DocumentElement->ChildNodes->Nodes[i], indent);
}
sRes += "</" + doc->DocumentElement->NodeName + ">/r/n";
return sRes;
}
AnsiString formatXMLNode(_di_IXMLNode element, int indent)
{
AnsiString sBlank = "";
AnsiString sRes = "";
int i;
for (i = 0; i < indent; ++i){
sBlank += " ";
}
if (element->NodeType == ELEMENT_NODE
&& element->ChildNodes && element->ChildNodes->Count > 0
&& element->ChildNodes->Nodes[0]->NodeType != TEXT_NODE)
{
sRes = sBlank + '<'+element->NodeName;
for (i = 0; i < element->AttributeNodes->Count; i++)
{
sRes += " " + element->AttributeNodes->Nodes[i]->NodeName
+ "=/"" + element->AttributeNodes->Nodes[i]->NodeValue + "/"";
}
sRes += ">/r/n";
indent++;
for (i = 0; i < element->ChildNodes->Count; i++)
{
sRes += formatXMLNode(element->ChildNodes->Nodes[i], indent);
}
sRes += sBlank + "</" + element->NodeName + ">/r/n";
}else if (element->NodeType != PROCESSING_INSTRUCTION_NODE)
{
sRes += sBlank + element->XML + "/r/n";
}
return sRes;
}
//声明:该代码源于网络,并做了些修改
AnsiString formatXMLDoc(TXMLDocument* doc, int indent)
{
AnsiString sRes;
int i;
sRes = "<?xml version=/"" + doc->Version + "/" encoding=/"" + doc->Encoding + "/"?>/r/n";
sRes += "<" + doc->DocumentElement->NodeName;
for (i = 0; i < doc->DocumentElement->AttributeNodes->Count; i++)
{
sRes += " " + doc->DocumentElement->AttributeNodes->Nodes[i]->NodeName
+ "=/"" + doc->DocumentElement->AttributeNodes->Nodes[i]->NodeValue + "/"";
}
sRes += ">/r/n";
for (i = 0; i < doc->DocumentElement->ChildNodes->Count; ++i){
sRes += formatXMLNode(doc->DocumentElement->ChildNodes->Nodes[i], indent);
}
sRes += "</" + doc->DocumentElement->NodeName + ">/r/n";
return sRes;
}
AnsiString formatXMLNode(_di_IXMLNode element, int indent)
{
AnsiString sBlank = "";
AnsiString sRes = "";
int i;
for (i = 0; i < indent; ++i){
sBlank += " ";
}
if (element->NodeType == ELEMENT_NODE
&& element->ChildNodes && element->ChildNodes->Count > 0
&& element->ChildNodes->Nodes[0]->NodeType != TEXT_NODE)
{
sRes = sBlank + '<'+element->NodeName;
for (i = 0; i < element->AttributeNodes->Count; i++)
{
sRes += " " + element->AttributeNodes->Nodes[i]->NodeName
+ "=/"" + element->AttributeNodes->Nodes[i]->NodeValue + "/"";
}
sRes += ">/r/n";
indent++;
for (i = 0; i < element->ChildNodes->Count; i++)
{
sRes += formatXMLNode(element->ChildNodes->Nodes[i], indent);
}
sRes += sBlank + "</" + element->NodeName + ">/r/n";
}
else if (element->NodeType != PROCESSING_INSTRUCTION_NODE)
{
sRes += sBlank + element->XML + "/r/n";
}
return sRes;
}
3、注意事项
以上描述的方式是通过XML控件方式来操作XML文档。在使用对象方式操作XML文件时,需要注意一些问题。
在加载一个文件时,不需要创建一个TXMLDocument对象(TXMLDocument *myxml = new TXMLDocument()),
而是使用_di_IXMLDocument接口。从文件加载XML文件是使用LoadXMLDocument来获得该接口的实例。操作
一个空的XML文档并开始写时也是使用该接口NewXMLDocument获得该接口。