我使用了boost序列化,但似乎无法生成符合特定模式的XML -- 它的目的似乎仅仅是持久化一个类的状态。
平台:Linux
你们用什么来生成而不是解析XML?
到目前为止,我走了Foredecker的路线,自己生成它 -- 这不是一个很大的文档,但我真的不应该在找到正确的库来生成它方面遇到这么多麻烦。
至于Boost,我想要能够设置节点名称,设置节点属性,并摆脱所有无关的东西,因为我其实并不关心将我的文档放回那个类中。
我使用了boost序列化,但似乎无法生成符合特定模式的XML -- 它的目的似乎仅仅是持久化一个类的状态。
平台:Linux
你们用什么来生成而不是解析XML?
到目前为止,我走了Foredecker的路线,自己生成它 -- 这不是一个很大的文档,但我真的不应该在找到正确的库来生成它方面遇到这么多麻烦。
至于Boost,我想要能够设置节点名称,设置节点属性,并摆脱所有无关的东西,因为我其实并不关心将我的文档放回那个类中。
我最近审查了一堆用于生成XML代码的XML库。
总结一下:我选择了TinyXML++。
TinyXML++具有良好的C++语法,基于成熟的TinyXML C库构建,是免费且开源(MIT许可证),而且很小。简而言之,它可以快速完成工作。以下是一个快速示例:
Document doc;
Node* root(doc.InsertEndChild(Element("RootNode")));
Element measurements("measurements");
Element tbr("TotalBytesReceived", 12);
measurements.InsertEndChild(tbr);
root->InsertEndChild(measurements);
生成如下:
<RootNode>
<measurements>
<TotalBytesReceived>12</TotalBytesReceived>
</measurements>
</RootNode>
我一直对它非常满意。
我审核了很多其他库,以下是一些更好的选择:
Xerces:最强大的库。它可以 做任何事情(尤其是与Xalan组合使用时),但是它很庞大,需要用户自行管理内存。
RapidXML:用于解析的速度 非常快,但是由于添加节点到DOM需要进行内存管理,因此不适用于生成。
Boost.XML(提议):看起来非常 棒 - 强大、优秀的C++语法。但它尚未经过审查过程,没有官方支持,可能会改变接口。我差点就用了这个库,期待它被纳入Boost。
Libxml(++):非常好;功能强大,语法不错。但如果你只是在生成XML,它会有点大,而且它与glibmm库(用于ustring)捆绑在一起。如果我们只使用Linux(像你一样?),我会认真考虑这个库。
XiMOL:独特的基于流的库。对于我们的需求来说,这个库有点过于简单了,但是对于基本的XML生成,你可能会发现它非常有用。其流语法非常简洁。
希望这些内容对你有所帮助!
有些人可能会认为我是XML异端,但一种有效的方法是使用您喜欢的字符串输出工具(print、输出流等)来生成它 - 这可以写入缓冲区或文件。
保存后,您应该在提交或发送之前使用模式进行验证。
对于我们的一个项目,我们有一组非常简单的模板来管理开始/结束标记和属性。每个模板都有一个流输出运算符。这使得生成源XML和调试非常容易。这使得XML生成代码的结构看起来非常像XML本身。
其中一个优点是,如果流式传输到文件,则可以高效地生成大量XML。您稍后将支付验证成本(可能是昂贵操作的更好时间)。
这种技术的缺点是它基本上只能输出。它不适用于动态创建然后消耗XML。
Boost.PropertyTree 是一种很好的且直接的生成XML的方式,特别是当你已经在使用Boost时。
以下是一个完整的示例程序:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using boost::property_tree::ptree;
using boost::property_tree::write_xml;
using boost::property_tree::xml_writer_settings;
int wmain(int argc, wchar_t* argv[]) {
char* titles[] = {"And Then There Were None", "Android Games", "The Lord of the Rings"};
ptree tree;
tree.add("library.<xmlattr>.version", "1.0");
for (int i = 0; i < 3; i++) {
ptree& book = tree.add("library.books.book", "");
book.add("title", titles[i]);
book.add("<xmlattr>.id", i);
book.add("pageCount", (i+1) * 234);
}
// Note that starting with Boost 1.56, the template argument must be std::string
// instead of char
write_xml("C:\\Users\\Daniel\\Desktop\\test.xml", tree,
std::locale(),
xml_writer_settings<char>(' ', 4));
return 0;
}
生成的XML如下:
<?xml version="1.0" encoding="utf-8"?>
<library version="1.0">
<books>
<book id="0">
<title>And Then There Were None</title>
<pageCount>234</pageCount>
</book>
<book id="1">
<title>Android Games</title>
<pageCount>468</pageCount>
</book>
<book id="2">
<title>The Lord of the Rings</title>
<pageCount>702</pageCount>
</book>
</books>
</library>
特别好的一点是使用点分隔路径可以隐式地创建所有节点。文档相对较少,但结合 ptree.hpp
应该可以让你了解它是如何工作的。documentation
使用哪个平台? 在Windows上,MSXML是一个选项。 CMarkup是另一个不错的选择。 如果可以使用.NET,它具有出色的XML支持。
我实际上还没有尝试使用boost序列化来做这件事,但据我了解,如果你非常小心地选择选项,你可以在模式中设置许多不同的选项(例如防止指针飞行权并为某些类型设置元素名称)
我使用tinyXml++,它使得像上面发布的那样创建xml非常容易。它还可以通过一个命令将其保存到文件中,但我找不到如何将其保存到缓冲区。