TinyXml怎样使用string初始化
wstring strTest = L“……..“;
TiXmlDocument* myDocument = new TiXmlDocument();
myDocument-》Parse( strTest.c_str());
如何利用tinyxml操纵xml及注意问题
创建的格式如下:
复制代码 代码如下:
《Persons》
《Person》
《name》lhy《/name》
《age》22《/age》
《/Person》
《/Persons》
上篇博客中,我们也介绍了tinyxml解析器中的所有的类以及类之间的关系。
创建上述格式的xml,代码如下:
复制代码 代码如下:
//创建一个XML的文档对象。
TiXmlDocument *myDocument = new TiXmlDocument();
//创建一个根元素并连接。
TiXmlElement *RootElement = new TiXmlElement(“Persons“);
myDocument-》LinkEndChild(RootElement);
//创建一个Person元素并连接。
TiXmlElement *PersonElement = new TiXmlElement(“Person“);
RootElement-》LinkEndChild(PersonElement);
//创建name元素、age元素并连接。
TiXmlElement *NameElement = new TiXmlElement(“name“);
TiXmlElement *AgeElement = new TiXmlElement(“age“);
PersonElement-》LinkEndChild(NameElement);
PersonElement-》LinkEndChild(AgeElement);
//设置name元素和age元素的内容并连接。
TiXmlText *NameContent = new TiXmlText(“lhy“);
TiXmlText *AgeContent = new TiXmlText(“22“);
NameElement-》LinkEndChild(NameContent);
AgeElement-》LinkEndChild(AgeContent);
myDocument-》SaveFile(“d:\\lhy\\xml.txt“);//保存到文件
只要搞清xml中节点之间的关系,创建不是问题。说白了就是一种辈分关系。
创建搞定了,但是作为C++程序猿,写完之后,总感觉有点别扭,总感觉哪不对劲。你是否也看出其中存在的猫腻?
对了,些许的代码中有大量的New指针。在C++中可没有java中的垃圾回收机制,必须自己来处理这些废弃的垃圾。但是代码中却没有Delete语句?
上网查了资料,发现很多创建代码中,都没有Delete语句?难道是大家都是复制粘贴?还是tinyxml在搞怪?
我总结了以下几点,但是最后在开发的过程中仍是疑问,但是开发的过程中,没有出现问题,所以我的程序就暂时如此了。
说法一:很多文章中,都是new没有delete,是因为tinyxml可以自动释放,自动销毁指针,无需开发者手动释放。
质疑:new出来的可以自动释放?new出来说明是在堆上创建的,什么时候会自动释放?程序结束时,自动释放?那怎么判断程序结束呢?(在一个模块中如何析构另一个模块中的内存区域,我们后面会详谈),所以这种说法不攻自破。
既然tinyxml中有自毁功能,那我们查询其源代码,发现果真如此,tinyxml中在析构函数中,有相应的指针释放。但是并不是每个节点如此的。
源码中的详情:
复制代码 代码如下:
TiXmlNode::~TiXmlNode()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node-》next;
delete temp;
}
}
void TiXmlNode::Clear()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node-》next;
delete temp;
}
firstChild = 0;
lastChild = 0;
}
我们也知道tinyxml中的类之间存在继承关系。
那我们看tinyxml中的TixmlElement类:
复制代码 代码如下:
TiXmlElement::~TiXmlElement()
{
ClearThis();
}
void TiXmlElement::ClearThis()
{
Clear();
while( attributeSet.First() )
{
TiXmlAttribute* node = attributeSet.First();
attributeSet.Remove( node );
delete node;
}
}
因为TixmlElement是继承TiXmlNode.但是在TiXmlDocument中并没有发现TiXmlDocument类的析构函数。
第二种说法:TiXmlDocument对象就是这棵树的根结点,
在一个完整的文档中, 除了它, 其余结点必须都是它的后代, 所以TinyXml用了一个很巧妙的方法来析构每一个结点所对应的对象 —-
每个结点的析构任务都委托给了它的父亲, 这样只要保证父亲被正确析构, 或者调用了父亲的Clear函数, 它的所有后代都会被正确的析构,
所以对整个文档来说只要TiXmlDocument对象被正确析构即可。
在创建的上述代码中,我们发现,所有的节点都是挂在根节点之下的。
其实这句代码: myDocument-》LinkEndChild(RootElement);使用了多态方式。类之间的关系如下:
并且LinkEndChild源代码如下:它是父类TiXmlNode中的方法
复制代码 代码如下:
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
{
assert( node-》parent == 0 || node-》parent == this );
assert( node-》GetDocument() == 0 || node-》GetDocument() == this-》GetDocument() );
if ( node-》Type() == TiXmlNode::DOCUMENT )
{
delete node;
if ( GetDocument() ) GetDocument()-》SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
return 0;
}
node-》parent = this;
node-》prev = lastChild;
node-》next = 0;
if ( lastChild )
lastChild-》next = node;
else
firstChild = node;// it was an empty list.
lastChild = node;
return node;
}
这样的话:则只要删除根节点,在程序中myDocument,就相当于把删除了TiXmlNode,相当于调用了TiXmlNode的析构函数。
质疑:网上说这种方式,析构是从叶子到树根。根据TiXmlNode中的析构函数,我们可以得出,是从树根到叶子。
但是我们在Delete myDocument时,应该注意一点:
创建文档时,也就是程序段中的myDocument。若是从堆上创建,则需需要手动释放。如我们上述的片段中,就是在堆上创建的。
TiXmlDocument *myDocument=new TiXmlDocument ();
若是从栈上创建,则不须我们手动释放,而是程序自动调用析构函数。同时我们应该注意,其他的元素必须在堆上创建。因为在TiXmlNode析构函数中,是delete的,但是栈上的东东是不须delete,所以除了根节点之外连接的后代节点是必须从堆上创建。
经过我们解释,明白tinyxml中的原理了吗?只要理解了tinyxml中的类的作用以及类之间的关系,看源码是没问题滴哦。
这篇博客根据创建xml小demo解释了其中存在的疑问。那下篇博客中我们会根据解析xml来答疑解析中存在的问题。
tinyxml 参数是ansi还是utf8
当通讯的xml里面含有中文字符的时候,tinyxml解析时总是报错,不能进行解析,查找原因后发现是tinyxml在解析UTF-8字符集的xml时,需要特殊指定字符集才行,下面是对于读取文件和直接解析字符串所需的tinyxml函数的使用方式。
一、需解析的xml
[html] view plain copy
《?xml version=“1.0“ encoding=“utf-8“?》
《Parament》
《SchedTempl》
《CommandType》2《/CommandType》
《SchedTemplID》1《/SchedTemplID》
《SchedType》0《/SchedType》
《SchedName》全天侯模板《/SchedName》
《MondaySched》111111111111111111111111111111111111111111111110《/MondaySched》
《TuesdaySched》111111111111111111111111111111111111111111111110《/TuesdaySched》
《WednesdaySched》111111111111111111111111111111111111111111111110《/WednesdaySched》
《ThursdaySched》111111111111111111111111111111111111111111111110《/ThursdaySched》
《FridaySched》111111111111111111111111111111111111111111111110《/FridaySched》
《SaturdaySched》111111111111111111111111111111111111111111111110《/SaturdaySched》
《SundaySched》111111111111111111111111111111111111111111111110《/SundaySched》
《/SchedTempl》
《SchedTempl》
《CommandType》2《/CommandType》
《SchedTemplID》2《/SchedTemplID》
《SchedType》0《/SchedType》
《SchedName》工作日模板《/SchedName》
《MondaySched》000000000000000000111111111111111110000000000000《/MondaySched》
《TuesdaySched》
000000000000000000111111111111111110000000000000《/TuesdaySched》
《WednesdaySched》
000000000000000000111111111111111110000000000000《/WednesdaySched》
《ThursdaySched》
000000000000000000111111111111111110000000000000《/ThursdaySched》
《FridaySched》
000000000000000000111111111111111110000000000000《/FridaySched》
《SaturdaySched》
000000000000000000000000000000000000000000000000《/SaturdaySched》
《SundaySched》
000000000000000000000000000000000000000000000000《/SundaySched》
《/SchedTempl》
《/Parament》
二、读取xml文件,tinyxml处理方式
[cpp] view plain copy
TiXmlDocument *xmlfile= new TiXmlDocument(FilePath);
xmlfile-》LoadFile(TIXML_ENCODING_UTF8);
三、读取xml字符串,tinyxml处理方式
[cpp] view plain copy
TiXmlDocument myDocument;
myDocument.Parse(xmlParament,0,TIXML_ENCODING_UTF8);
//或者myDocument.Parse(xmlParament,0,TIXML_ENCODING_LEGACY);
if( !myDocument.Error() ){
TiXmlElement* paramentEle = myDocument.FirstChildElement(PARAMENT_PARENT_NODE_NAME);
if (paramentEle==NULL)
{
return FALSE;
}
TiXmlElement* schedTemplEle = paramentEle-》FirstChildElement(“SchedTempl“);
while(schedTemplEle)
{
RecordScheduleTemplateInfo templInfo;
TIXML_NODE_VALUE_FROM_PARENT(schedTemplEle,“SchedTemplID“,&templInfo.schedTemplId);
TIXML_NODE_VALUE_FROM_PARENT(schedTemplEle,“SchedType“,&templInfo.schedType);
templInfo.schedName = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“SchedName“,““);
templInfo.mondaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“MondaySched“,““);
templInfo.tuesdaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“TuesdaySched“,““);
templInfo.wednesdaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“WednesdaySched“,““);
templInfo.thursdaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“ThursdaySched“,““);
templInfo.fridaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“FridaySched“,““);
templInfo.saturdaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“SaturdaySched“,““);
templInfo.sundaySched = TIXML_NODE_TEXT_FROM_PARENT(schedTemplEle,“SundaySched“,““);
this-》schedTemplInfoList.push_back(templInfo);
schedTemplEle = schedTemplEle-》NextSiblingElement();
}
}
说明(引用官方的翻译)
一般地,TinyXML 试着检测正确的编码方式并使用它。但是,可以通过在头文件中设置 TIXML_DEFAULT_ENCODING 的值来强制使用某一种编码方式。
TinyXML 将要假设一种合法模式,直到一下的其中之一发生:
1)如果不是标准的,但是 UTF-8 带头字节(UTF-8 lead bytes)出现在文件或数据流的头部,TinyXML 将按照 UTF-8 的编码方式读取。
2)如果声明的标签被读取,并且它有个 encoding=“UTF-8“,则按照 UTF-8 编码方式读取。
3)如果声明的标签被读取,它没有特殊的编码,则按照 UTF-8 编码。
4)如果声明表中是 encoding=“something else“,TinyXML 将其读作为合法模式(legacy mode)。在合法模式中,TinyXML 和以前工作一样。不清楚具体是哪种模式,老的内容应该保持工作。
5)直到上面的一种准则满足,TinyXML 按照合法模式执行。
如果编码是不正确的,或者被检测出来将要发生什么?TinyXML 将其看做不合适的编码。你可能得到的是不正确的结果或乱码。你可能想强制 TinyXML 变为正确的模式。
这一通过 LoadFile( TIXML_ENCODING_LEGACY ) 或者 LoadFile( filename, TIXML_ENCODING_LEGACY ) 的方式强制 TinyXML 设置为合法模式。你可以设置 TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY 来一直使用合法模式。同样地,你也可以使用同样的技术将其设置为 TIXML_ENCODING_UTF8。
对于英语用户,使用英文的 XML,UTF-8 与 low-ASCII 是一样的,你不需要检测 UTF-8 或者改变你的代码。可以将 UTF-8 看做 ASCII 的一个超集。
UTF-8 不是双字节格式,但是它是 Unicode 的标准编码。
TinyXML 不使用和直接同时支持 wchar, TCHAR, 或者 微软的 _UNICODE。
用 Unicode 指代 UTF-16 是不合适的,UTF-16 是 Unicode 的一种宽字节编码方式。这引起了混乱。
对于 high-ascii 语言,TinyXML 可以处理所有的语言,同时,只要 XML 被编码成 UTF-8。这样有些滑稽,老的程序员和操作系统趋向于使用 default 和 traditional 的代码页。许多应用可以输出 UTF-8,但是老或者顽固的应用是以默认的代码页输出文本的。
用tinyxml创建xml文件
——需要的包
#include 《XMLDoc.hpp》
——相关说明
_di_IXMLDocument 为模板类
typedef System::DelphiInterface《 IXMLDocument 》 _di_IXMLDocument;
_di_IXMLNode
typedef System::DelphiInterface《 IXMLNode 》 _di_IXMLNode;
_di_IXMLNodeList 同
——类方法
//设置参数
void TXXX::setOptions(String name,String value){
//创建文档对象
_di_IXMLDocument XMLDoc = LoadXMLDocument(L“文件路径“);
XMLDoc-》Active=true;
//文档根节点
_di_IXMLNode root = XMLDoc-》DocumentElement;
//想要查找节点
_di_IXMLNode tempNode;
//调用搜索方法
searchXml(name,root,tempNode);
// 处理
if(tempNode!=NULL)
tempNode-》SetText(value);
XMLDoc-》SaveToFile(L“文件路径“);
}
//递归搜索参数节点树
void TXXX::searchXml(String name,_di_IXMLNode &Parent_Node,_di_IXMLNode& tempNode){
_di_IXMLNode Child_Node; //子结点
//子节点列表
_di_IXMLNodeList list = Parent_Node-》ChildNodes;
for(int i=0;i《list-》Count;i++)
{
Child_Node = list-》Get(i);
//递归结束条件
if(Child_Node-》GetNodeName()==name)
{
tempNode = Child_Node;
break;
}
else
{
//递归函数
searchXml(name,Child_Node,tempNode);
}
}
}
tinyxml怎么改变xml文件的编码
关于tinyxml使用的文档有很多(这篇文章就写的很好),这里仅提一下字符编码的转换问题,如果你不熟悉字符编码最好先阅读一下计算机内存和文件中的UNICODE字符.
tinyxml定义的类或函数中涉及的字符大都是char,字符串指针也是char*或const char*,看一下面几个函数:
const char* TiXmlElement::Attribute( const char* name ) const
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
…
这样在你的应用程序中获取的字符串就是const char*类型,如果你的XML文档指定是UTF-8编码(注意保存的时候也是以UTF-8编码方式保存的),例如:
《?xml version=“1.0“ encoding=“UTF-8“》
《root》
《item》中文字符《/item》
《/root》
而你的应用程序可能是UNICODE,也可能是多字节,那么在应用程序中会这样读xml文档:
TiXmlDocument doc(“UTF8test.xml“);
doc.LoadFile(TIXML_DEFAULT_ENCODING);//TIXML_DEFAULT_ENCODING指明按照UTF-8编码方式读取xml文档
TiXmlElement* root = doc.RootElement();
TiXmlNode* node = root-》FirstChild(“item“);
TiXmlElement* element = node-》ToElement();
const char* text = element-》GetText();