我必须用C++解析XML文件.我正在研究并找到了RapidXml库.
我对此表示怀疑doc.parse<0>(xml).
可以xml是.xml文件,还是需要是?string或char *?
如果我只能使用string或者char *我想我需要读取整个文件并将其存储在char数组中并将其指针传递给函数?
有没有办法直接使用文件,因为我还需要更改代码中的XML文件.
如果在RapidXml中无法做到这一点,请在C++中推荐一些其他XML库.
谢谢!!!
Ashd
我一直在搞乱在我的一个项目中使用RapidXML.直到我决定使用它写出xml之前,一切都进展顺利.我的代码或多或少如下:
//attempt to open the file for writing
std::ofstream file(fileName.c_str());
if (!file.is_open())
return false; //the file didn't open
xml_document<> doc;
//creates the contents of the document...
//...
//...
//write the document out to the file
file << doc; //if I remove this line it compiles...but I kinda need this line to output to the file
file.close();
Run Code Online (Sandbox Code Playgroud)
在编译时,我收到以下错误:
In file included from ../Engine/xmlfileloader.cpp:12:0:
../Engine/include/rapidxml_print.hpp: In instantiation of 'OutIt rapidxml::internal::print_node(OutIt, const rapidxml::xml_node<Ch>*, int, int) [with OutIt = std::ostream_iterator<char, char, std::char_traits<char> >; Ch …Run Code Online (Sandbox Code Playgroud) 在我的C++程序中,我想解析一小段XML,插入一些节点,然后提取新的XML(最好是一个std::string).
RapidXml已被推荐给我,但我看不到如何将XML作为文本字符串检索回来.
(我可以遍历节点和属性并自己构建它,但肯定有一个我缺少的功能构建.)
谢谢.
RapidXML是一个快速,轻量级的C++ XML DOM Parser,但它有一些怪癖.
我想到的最糟糕的是:
3.2字符串的所有权.
RapidXml生成的节点和属性不拥有其名称和值字符串.他们只是指着他们.这意味着在使用
xml_base::name(const Ch *)或xml_base::value(const Ch *)函数手动设置这些值时必须小心.必须注意确保传递的字符串的生命周期至少与节点/属性的生命周期一样长.实现它的最简单方法是从文档拥有的memory_pool中分配字符串.使用
memory_pool::allocate_string()功能用于此目的.
现在,我明白它是以这种方式为速度做的,但这感觉就像车祸等待发生.以下代码看起来无害,但当foo返回时,'name'和'value'超出范围,因此doc未定义.
void foo()
{
char name[]="Name";
char value[]="Value";
doc.append_node(doc.allocate_node(node_element, name, value));
}
Run Code Online (Sandbox Code Playgroud)
根据allocate_string()手动工作使用的建议,但它很容易忘记.
有没有人'增强'RapidXML来避免这个问题?
使用rapidxml我想循环遍历一组节点,并且使用我发现的最好的方法(从可靠的stackoverflow,doc似乎没有迭代的例子):
while (curNode->next_sibling() !=NULL ) {
string shiftLength = curNode->first_attribute("shiftLength")->value();
cout << "Shift Length " << "\t" << shiftLength << endl;
curNode = curNode->next_sibling();
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,在我的OSX 10.6 上,这就省去了最后一个兄弟节点 - 我想因为在循环的最后一次迭代中,next_sibling被调用了两次.如果我在循环之后写,我可以得到最后一个节点:
cout << " LAST IS: " << curNode->first_attribute("shiftLength")->value();
Run Code Online (Sandbox Code Playgroud)
......但那很狡猾,程序就此退出.
第一个问题:这可能是我设置的唯一缺陷(OSX 10.6)还是我编码错了?
第二个问题:有没有人有一个他们认为使用rapidxml迭代未知数量的XML节点的正确方法的例子?
多谢你们
皮特
我刚开始使用rapidXML,因为它被推荐给我.现在迭代多个兄弟姐妹我这样做:
//get the first texture node
xml_node<>* texNode = rootNode->first_node("Texture");
if(texNode != 0){
string test = texNode->first_attribute("path")->value();
cout << test << endl;
}
//get all its siblings
while(texNode->next_sibling() != 0){
string test = texNode->first_attribute("path")->value();
cout << test << endl;
texNode = texNode->next_sibling();
}
Run Code Online (Sandbox Code Playgroud)
作为基本测试,它工作正常.无论如何,我遇到了node_iterator,这对我来说似乎是一个额外的迭代器类.无论如何,我找不到任何关于如何使用它的例子,所以我想知道是否有人可以告诉我:)
谢谢!
我正在尝试将rapidxml 包含到我当前的项目中。但是,它不会构建。
Visual Studio 会抱怨这段代码 (rapidxml.hpp:419+451):
419: void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
420: xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
Run Code Online (Sandbox Code Playgroud)
编译器会说
Rapidxml.hpp(420):错误 C2061:语法错误:标识符“内存”
我有点明白这会如何混淆编译器。它实际上也让我很困惑。什么(memory)的一部分new(memory) xml_attribute<Ch>做什么呢?
如果我删除那(memory)部分,它编译就好了。
此外,gcc 编译它就好了(memory)。
编辑:
哦,我重载new了DEBUG_NEW做一些内存调试。DEBUG_NEW不支持新放置。
我最近开始使用 RapidXML,解析值很好(我可以从元素内部获取数据),但我想编辑元素内部的值。
为了这个程序的目的,我想把这个:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<data>
This is data.
</data>
</root>
Run Code Online (Sandbox Code Playgroud)
进入这个:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<data>
Edited!
</data>
</root>
Run Code Online (Sandbox Code Playgroud)
我在某处读到rapidxml::xml_node有一个value()函数来更改元素内部的值,但它似乎不起作用。当我写出文件时,我得到了与以前完全相同的东西。这是我的代码:
std::string input_xml = loadFile(filename);
std::vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.push_back('\0');
rapidxml::xml_document<> doc;
doc.parse<rapidxml::parse_declaration_node | rapidxml::parse_non_destructive>(&xml_copy[0]);
// Also tried with doc.parse<0>(&xml_copy[0]) but no luck
rapidxml::xml_node<>* root_node = doc.first_node("root");
root_node->first_node("data")->value(std::string("Edited!").c_str());
std::string data = std::string(xml_copy.begin(), xml_copy.end());
std::ofstream file;
file.open(filename.c_str());
file << data;
file.close();
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
编辑:
结合接受的答案,该parse()函数还需要具有rapidxml::parse_no_data_nodes标志:
std::string input_xml = TileManager::getData(filename);
std::vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.push_back('\0'); …Run Code Online (Sandbox Code Playgroud) RapidXml的文档说
池维护静态分配的内存的RAPIDXML_STATIC_POOL_SIZE个字节.在静态内存耗尽之前,不会进行动态内存分配.当静态内存耗尽时,pool通过使用global new []和delete []运算符分配额外的内存大小为RAPIDXML_DYNAMIC_POOL_SIZE的内存块
我将其解释为:RapidXML使用全局内存池.全局内存池线程上的操作是否安全?即,我可以在整个程序中使用RapidXML解析器的多个实例,而不必考虑线程问题吗?
我在使用RapidXML解析字符串时遇到了一些麻烦.我在Eclipse中收到一条错误,声称解析函数不存在.
make all
Building file: ../search.cpp
Invoking: Cross G++ Compiler
g++ -DDEBUG -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"search.d" -MT"search.d" -o "search.o" "../search.cpp"
../search.cpp: In function ‘void search(CURL*, CURLcode, std::string, std::string)’:
../search.cpp:29:27: error: no matching function for call to ‘rapidxml::xml_document<>::parse(const char*)’
../search.cpp:29:27: note: candidate is:
../rapidxml-1.13/rapidxml.hpp:1381:14: note: template<int Flags> void rapidxml::xml_document::parse(Ch*) [with int Flags = Flags, Ch = char]
make: *** [search.o] Error 1
Run Code Online (Sandbox Code Playgroud)
以下代码引发错误:
rapidxml::xml_document<> doc; // This has no errors
doc.parse<0>(data.c_str()); // This line raises the error …Run Code Online (Sandbox Code Playgroud)