【问题标题】:C++ Using RapidXml parsing XML File, Wrapper Class, parse_error expect >C++ 使用 RapidXml 解析 XML 文件,包装类,parse_error 期望 >
【发布时间】:2013-08-27 01:17:41
【问题描述】:

我正在尝试使用 RapidXML 来解析我的 XML 文件。我是按照example here 做的。我没有在主函数中进行解析,而是编写了一个名为 XMLParser 的包装类来完成解析工作。这真的让我很头疼。

XMLParser.hpp:

#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include "rapidxml/rapidxml.hpp"

using namespace std;
using namespace rapidxml;

class XMLParser {

public:
    XMLParser() {};

    XMLParser(const std::string &xmlString): xmlCharVector(xmlString.begin(), xmlString.end())
    {
        //xmlCharVector.push_back('\0');
         parseXML();
    }
    XMLParser(const std::vector<char> &_xmlVector):xmlCharVector(_xmlVector)
    {
        /* xmlCharVector.push_back('\0'); */  // already done in main.cpp
        if (xmlCharVector != _xmlVector)      //And it turns out they're the same....
            std::cout << "The two vectors are not equal" << std::endl;
        else
            std::cout << "They are the same" << std::endl;
        parseXML();
    }

private:
    std::vector<char> xmlCharVector;
    rapidxml::xml_document<> doc;
    void parseXML();

};

XMLParser.cpp:

#include "XMLParser.hpp"

using namespace std;
using namespace rapidxml;

void XMLParser::parseXML()
{
    doc.parse<0>(&xmlCharVector[0]);
}

这里是 ma​​in.cpp:

#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include "XMLParser.hpp"

using namespace std;
using namespace rapidxml;

int main(int argc, char **argv)
{
    xml_document<> doc;
    xml_node<> *root_node;
    ifstream theFile("beer.xml");
    vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
    buffer.push_back('\0');

    doc.parse<0>(&buffer[0]);

    root_node = doc.first_node("MyBeerJournal");
    xml_node<> *engine = root_node->first_node("Brewery");

    //The above code works pretty well, and I can get the element I want in XML file.

    //The problem occurs when I tried to use the XMLParser
    XMLParser xmlParser(buffer);
    return 0;
}

main 函数中的解析过程运行良好。但是当我尝试在我的包装类parseXML() 中使用该函数时,出现了错误:

在抛出 'rapidxml::parse_error' 实例后调用终止 什么():预期> 中止(核心转储)

原来我在这个函数中有其他代码,但我把它们都注释了,发现即使是单行doc.parse&lt;0&gt;(&amp;xmlCharVector[0]);。为什么它在 main.cpp 中运行良好而不在包装类中运行良好?我实在想不通。有人能帮帮我吗?

【问题讨论】:

    标签: c++ xml wrapper parse-error rapidxml


    【解决方案1】:

    我找到了原因...这个愚蠢的问题确实需要我很长时间才能调试。我在这里写它是为了让任何人遇到它(希望不是)可以节省他的时间。问题恰恰在于main 函数中的代码doc.parse&lt;0&gt;(&amp;buffer[0])。在执行这行代码之前,buffer(type of vector&lt;char&gt;) 是这样的:(通过将向量打印到控制台)

    <MyBeerJournal>
        <Brewery name="Founders Brewing Company" location="Grand Rapids, MI">
            <Beer name="Centennial" description="IPA" rating="A+" dateSampled="01/02/2011">
                "What an excellent IPA. This is the most delicious beer I have ever tasted!"
            </Beer>
        </Brewery>
        .....
        .....
    </MyBeerJournal>
    

    与原始xml文件相同。执行上述代码后,buffer(type of vector&lt;char&gt;)变成了这样:

    <MyBeerJournal
        <Breweryname"Founders Brewing Company location"Grand Rapids, MI>
    
            <Beername"Centennial description"IPA rating"A+ dateSampled"01/02/2011>
    
                "What an excellent IPA. This is the most delicious beer I have ever tasted!"
            /Beer>
    
        </Brewery>
    

    如您所见,一些天使括号消失了。还有一些其他的东西,比如双引号也被改变了。所以包装类构造函数复制了修改后的“xml缓冲区”,而这个格式不好的xml向量肯定会导致包装类中的第二个doc.parse&lt;0&gt;(&amp;xmlCharVector[0]);失败。我不知道为什么库作者需要修改传入的char向量,因为一旦创建了DOC,后续的xml分析就与原始的char向量无关了。

    【讨论】:

    • '我不知道为什么库编写者需要修改传入的 char 向量' - 因为 RapidXML 被设计成超快的in-原位解析器。它创建的 DOM 只是指向原始数据的一组指针。阅读文档,特别是关于“与常规 XML 解析器的区别”的部分。 rapidxml.sourceforge.net/manual.html
    • @Roddy 这是否意味着该函数将直接使用指针编辑原始字符串,而不是先复制它然后对复制的字符串做一些事情?
    • 完全正确:除非您使用“非破坏性”模式,否则它会输入空字符来终止每个“节点”。这避免了分配存储来保存每个节点的速度开销,以及需要第二个未修改副本的内存开销。
    • @Roddy Gotcha!谢谢!
    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 2013-02-22
    • 2021-03-27
    相关资源
    最近更新 更多