Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用Boost访问解析XML并填充属性树_C++_Xml_Parsing_Boost_Boost Propertytree - Fatal编程技术网

C++ 使用Boost访问解析XML并填充属性树

C++ 使用Boost访问解析XML并填充属性树,c++,xml,parsing,boost,boost-propertytree,C++,Xml,Parsing,Boost,Boost Propertytree,我有一个XML文件: <expressions> <addition id="1"> <item>2</item> <item>3</item> <item>4</item> </addition> <subtraction id="2"> <minuend>3</minu

我有一个XML文件:

<expressions>
    <addition id="1">
        <item>2</item>
        <item>3</item>
        <item>4</item>
    </addition>
    <subtraction id="2">
        <minuend>3</minuend>
        <subtrahend>2</subtrahend>
    </subtraction>
    <multiplication id="3">
        <factor>5</factor>
        <factor>6</factor>
        <factor>8</factor>
    </multiplication>
    <division id="4">
        <dividend>54</dividend>
        <divisor>9</divisor> 
    </division>
</expressions>
继承的类有
加法表达式
减法表达式
乘法表达式
除法表达式

除此之外,我还在每个继承类中实现了数据操作方法

最后,我编写了一些代码,计算了这些XML:

using boost::property_tree::ptree;
    ptree pt;
    read_xml("/PATH_TO/valuator.xml", pt);
    const ptree & expressions = pt.get_child("expressions");
    BOOST_FOREACH(const ptree::value_type & currExpr, expressions){
        std::string readExprType = currExpr.first;
        std::cout << "currExpr = " << readExprType << std::endl;

        if (readExprType == "addition") {
            AbstractExpression *addExpr = new additionExpression();
            BOOST_FOREACH(const ptree::value_type & additionNodeEl, currExpr.second){
                std::string val = additionNodeEl.second.data();
                ((additionExpression*)addExpr)->addVal( atoi(val.c_str()) );

            }
            std::cout << "addition result = " << addExpr->evalExpr() << std::endl;
            delete addExpr;
        } else if (readExprType == "multiplication") {
            AbstractExpression *multExpr = new multiplicationExpression();
            BOOST_FOREACH(const ptree::value_type &multNodeEl, currExpr.second) {
                std::string val = multNodeEl.second.data();
                if (!val.empty())
                    ((multiplicationExpression*)multExpr)->addVal( atoi(val.c_str()) );
            }
            std::cout << "multiplication node result = " << multExpr->evalExpr() << std::endl;
            delete multExpr;
        } else if (readExprType == "subtraction") {
            AbstractExpression *substrExpr = new substractionExpression();
            BOOST_FOREACH(const ptree::value_type &substNodeEl, currExpr.second) {
                std::string elTypeName = substNodeEl.first;
                std::string val = substNodeEl.second.data();
                if (elTypeName == "minuend") {
                    ((substractionExpression*)substrExpr)->setMinuend( atoi(val.c_str()) );
                } else if (elTypeName == "subtrahend") {
                    ((substractionExpression*)substrExpr)->setSubtrahend( atoi(val.c_str()) );
                }
            }
            std::cout << "subtraction node result = " << substrExpr->evalExpr() << std::endl;
            delete substrExpr;
        } else if (readExprType == "division") {
            AbstractExpression *divExpr = new divisionExpression();
            BOOST_FOREACH(const ptree::value_type &divNodeEl, currExpr.second) {
                std::string elTypeName = divNodeEl.first;
                std::string val = divNodeEl.second.data();
                if ( elTypeName == "dividend" ) {
                    ((divisionExpression*)divExpr)->setDividend( atoi(val.c_str()) );
                } else if ( elTypeName == "divisor" ) {
                    ((divisionExpression*)divExpr)->setDivisor( atoi(val.c_str()) );
                }
            }
            std::cout << "dividend node result = " << divExpr->evalExpr() << std::endl;
            delete divExpr;
        }

    }
使用boost::property_tree::ptree;
ptree-pt;
读取xml(“/PATH\u TO/evaluator.xml”,pt);
const ptree&expressions=pt.get_child(“表达式”);
BOOST_FOREACH(const ptree::value_type和currExpr,表达式){
std::string readExprType=currExpr.first;

std::cout实际上,使用适当的XML库(TinyXML、RapidXML、PugiXML、libxml2等)

如果您真的只关心XML的一个非常特定的子集,那么这里有一个基于Boost Spirit V2的快速而肮脏的解析器:

namespace /*parser*/
{
    namespace qi = boost::spirit::qi;

    template <typename It, typename Skipper = qi::space_type>
        struct grammar : qi::grammar<It, ast::expressions(), Skipper>
    {
        grammar() : grammar::base_type(expressions_)
        {
            using namespace qi;

            static const lexeme_type L;

            simplevalue_ = auto_; // parses into Value, whatever it was declared as
            id_attr      = eps >> L["id"]      > '=' > '"' > int_        > '"';
            complex_attr = eps >> L["complex"] > '=' > '"' > *~char_('"') > '"';
            expr_open    = eps >> '<' >> L[lit(_r1)] > -id_attr > -complex_attr > '>';
            expr_close   = eps >> '<' >> '/' > L[lit(_r1)] > '>';

            // expression element parsing
            addition_       = expr_open(+"addition") > +subexpr_(+"item")                                  > expr_close(+"addition");
            subtraction_    = expr_open(+"subtraction") > (subexpr_(+"minuend") > subexpr_(+"subtrahend")) > expr_close(+"subtraction");
            multiplication_ = expr_open(+"multiplication") > +subexpr_(+"factor")                          > expr_close(+"multiplication");
            division_       = expr_open(+"division") > (subexpr_(+"dividend") > subexpr_(+"divisor"))      > expr_close(+"division");
            expression_     = simplevalue_ | addition_ | subtraction_ | multiplication_ | division_;

            subexpr_ = eps >> '<' >> L[lit(_r1)] > '>' > expression_ > '<' > '/' > L[lit(_r1)] > '>';

            expressions_ = eps
                > '<' > L["expressions"] > '>'
                > *expression_
                > expr_close(+"expressions");

            BOOST_SPIRIT_DEBUG_NODES((simplevalue_)(expr_open)(expr_close)(subexpr_)(addition_)(subtraction_)(multiplication_)(division_)(expression_)(expressions_))
        }
      private:
        template <typename... T>
            using Rule = qi::rule<It, T..., qi::space_type>;

        // tags/primitives
        Rule<> complex_attr;
        Rule<int()> id_attr;
        Rule<ast::Value()> simplevalue_;
        Rule<ast::Id(std::string element_name)> expr_open;
        Rule<void(std::string element_name)> expr_close;

        Rule<ast::expression(std::string element_name )> subexpr_;

        // compounds
        Rule<ast::addition()>       addition_;
        Rule<ast::subtraction()>    subtraction_;
        Rule<ast::multiplication()> multiplication_;
        Rule<ast::division()>       division_;
        Rule<ast::expression()>     expression_;

        Rule<ast::expressions()> 
            expressions_;
    };

} /*parser*/
namespace/*解析器*/
{
名称空间qi=boost::spirit::qi;
模板
结构语法:qi::grammar
{
语法():语法::基本类型(表达式)
{
使用名称空间qi;
静态常量词素类型L;
simplevalue_u=auto_;//解析为值,不管它声明为什么
id_attr=eps>>L[“id”]>'='>''''''>'''>int_>'''>;
复数字符属性=eps>>L[“复数”]>'='>''>'>'>*~char(''''')>'';
expr_open=eps>>'';
expr_close=eps>>'';
//表达式元素解析
添加=扩展打开(+“添加”)>+子扩展(+“项”)>扩展关闭(+“添加”);
减法运算=减法运算打开(+“减法”)>减法运算结束(+“减法”)>减法运算结束(+“减法”);
乘法=expr\u打开(+“乘法”)>+子表达式(+“因子”)>expr\u关闭(+“乘法”);
分部=开放式(+“分部”)>(分分部(+“股息”)>分分部(+“分部”)>分分部关闭式(+“分部”);
表达式=simplevalue |加法|减法|乘法|除法|;
子表达式=eps>>>'>表达式;
表达式=eps
> ''
>*表达_
>expr_close(+“表达式”);
BOOST_-SPIRIT_-DEBUG_节点((simplevalue_)(expr_打开)(expr_关闭)(subexpr_)(加法(减法)(乘法)(除法)(表达式)(表达式))
}
私人:
模板
使用Rule=qi::Rule;
//标记/原语
规则复杂性;
规则id_attr;
规则


注意:不处理注释、unicode、处理指令、名称空间、PCDATA、字符实体引用等。简而言之,这不是一个XML解析器

对于消息格式,特别是源代码,很抱歉。请将结果放入映射并稍后将XML作为文本写入OK,但如何获取“id”来自ThanksThanks allot,但此任务还有另一种情况(刚得到更新),标记为“complex”的复杂节点:`2 3 7 3`提前感谢您的帮助!顺便说一句,您的解决方案在我尝试编译时生成了错误消息:simpleVal.cpp:21:30:error:const类型“const lexeme_type”(也称为“const expr”)的对象的默认初始化需要用户提供的默认构造函数static const lexeme_type L;^1生成错误。您使用的是哪种boost版本?@OleksandrHryhorchuk这对您来说是
clang
。没错。尽管此AFAIR的标准存在缺陷报告。(正如您在我的回答中所注意到的,它包括初始值设定项)一般来说,我几乎完成了这项任务,但我仍然是属性树和ream_xml。顺便说一下,要读取属性(在我前面的问题中),我们需要:
auto second=currExpr.second;second.get(.id”)
只是为了向其他人澄清。@OleksandrHryhorchuk您应该回答这个问题。无论如何,这里有一个版本也可以处理子表达式。现在完成AST表示。在可以看到它的地方查看它计算:2和-6138.58(看吧!没有显式的动态分配)。
using boost::property_tree::ptree;
    ptree pt;
    read_xml("/PATH_TO/valuator.xml", pt);
    const ptree & expressions = pt.get_child("expressions");
    BOOST_FOREACH(const ptree::value_type & currExpr, expressions){
        std::string readExprType = currExpr.first;
        std::cout << "currExpr = " << readExprType << std::endl;

        if (readExprType == "addition") {
            AbstractExpression *addExpr = new additionExpression();
            BOOST_FOREACH(const ptree::value_type & additionNodeEl, currExpr.second){
                std::string val = additionNodeEl.second.data();
                ((additionExpression*)addExpr)->addVal( atoi(val.c_str()) );

            }
            std::cout << "addition result = " << addExpr->evalExpr() << std::endl;
            delete addExpr;
        } else if (readExprType == "multiplication") {
            AbstractExpression *multExpr = new multiplicationExpression();
            BOOST_FOREACH(const ptree::value_type &multNodeEl, currExpr.second) {
                std::string val = multNodeEl.second.data();
                if (!val.empty())
                    ((multiplicationExpression*)multExpr)->addVal( atoi(val.c_str()) );
            }
            std::cout << "multiplication node result = " << multExpr->evalExpr() << std::endl;
            delete multExpr;
        } else if (readExprType == "subtraction") {
            AbstractExpression *substrExpr = new substractionExpression();
            BOOST_FOREACH(const ptree::value_type &substNodeEl, currExpr.second) {
                std::string elTypeName = substNodeEl.first;
                std::string val = substNodeEl.second.data();
                if (elTypeName == "minuend") {
                    ((substractionExpression*)substrExpr)->setMinuend( atoi(val.c_str()) );
                } else if (elTypeName == "subtrahend") {
                    ((substractionExpression*)substrExpr)->setSubtrahend( atoi(val.c_str()) );
                }
            }
            std::cout << "subtraction node result = " << substrExpr->evalExpr() << std::endl;
            delete substrExpr;
        } else if (readExprType == "division") {
            AbstractExpression *divExpr = new divisionExpression();
            BOOST_FOREACH(const ptree::value_type &divNodeEl, currExpr.second) {
                std::string elTypeName = divNodeEl.first;
                std::string val = divNodeEl.second.data();
                if ( elTypeName == "dividend" ) {
                    ((divisionExpression*)divExpr)->setDividend( atoi(val.c_str()) );
                } else if ( elTypeName == "divisor" ) {
                    ((divisionExpression*)divExpr)->setDivisor( atoi(val.c_str()) );
                }
            }
            std::cout << "dividend node result = " << divExpr->evalExpr() << std::endl;
            delete divExpr;
        }

    }
namespace /*parser*/
{
    namespace qi = boost::spirit::qi;

    template <typename It, typename Skipper = qi::space_type>
        struct grammar : qi::grammar<It, ast::expressions(), Skipper>
    {
        grammar() : grammar::base_type(expressions_)
        {
            using namespace qi;

            static const lexeme_type L;

            simplevalue_ = auto_; // parses into Value, whatever it was declared as
            id_attr      = eps >> L["id"]      > '=' > '"' > int_        > '"';
            complex_attr = eps >> L["complex"] > '=' > '"' > *~char_('"') > '"';
            expr_open    = eps >> '<' >> L[lit(_r1)] > -id_attr > -complex_attr > '>';
            expr_close   = eps >> '<' >> '/' > L[lit(_r1)] > '>';

            // expression element parsing
            addition_       = expr_open(+"addition") > +subexpr_(+"item")                                  > expr_close(+"addition");
            subtraction_    = expr_open(+"subtraction") > (subexpr_(+"minuend") > subexpr_(+"subtrahend")) > expr_close(+"subtraction");
            multiplication_ = expr_open(+"multiplication") > +subexpr_(+"factor")                          > expr_close(+"multiplication");
            division_       = expr_open(+"division") > (subexpr_(+"dividend") > subexpr_(+"divisor"))      > expr_close(+"division");
            expression_     = simplevalue_ | addition_ | subtraction_ | multiplication_ | division_;

            subexpr_ = eps >> '<' >> L[lit(_r1)] > '>' > expression_ > '<' > '/' > L[lit(_r1)] > '>';

            expressions_ = eps
                > '<' > L["expressions"] > '>'
                > *expression_
                > expr_close(+"expressions");

            BOOST_SPIRIT_DEBUG_NODES((simplevalue_)(expr_open)(expr_close)(subexpr_)(addition_)(subtraction_)(multiplication_)(division_)(expression_)(expressions_))
        }
      private:
        template <typename... T>
            using Rule = qi::rule<It, T..., qi::space_type>;

        // tags/primitives
        Rule<> complex_attr;
        Rule<int()> id_attr;
        Rule<ast::Value()> simplevalue_;
        Rule<ast::Id(std::string element_name)> expr_open;
        Rule<void(std::string element_name)> expr_close;

        Rule<ast::expression(std::string element_name )> subexpr_;

        // compounds
        Rule<ast::addition()>       addition_;
        Rule<ast::subtraction()>    subtraction_;
        Rule<ast::multiplication()> multiplication_;
        Rule<ast::division()>       division_;
        Rule<ast::expression()>     expression_;

        Rule<ast::expressions()> 
            expressions_;
    };

} /*parser*/
int main()
{
    std::ifstream ifs("expressions.xml");
    It f(ifs >> std::noskipws), l;

    try {
        ast::expressions parsed;

        grammar<It> g;
        // parsing
        bool ok = phrase_parse(f, l, g, qi::space, parsed);

        // output results
        if (ok)
        {
            eval::machine machine;

            std::cout << "<expressions>\n";
            for (auto& expr : parsed)
                if (get_id(expr))
                    std::cout << "\t<result id=\"" << *get_id(expr) << "\">" << machine.evaluate(expr) << "</result>\n";
            std::cout << "</expressions>\n";
        }
    } catch(qi::expectation_failure<It> const& e) {
        std::cout << "Expected " << e.what_ << " at '" << std::string(e.first,e.last) << "'\n";
    }
}
<expressions>
    <result id="1">9</result>
    <result id="2">1</result>
    <result id="3">240</result>
    <result id="4">6</result>
</expressions>