我有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一样提供结果:
<expressions>
<result id="1">9</result>
<result id="2">1</result>
<result id="3">240</result>
<result id="4">6</result>
</expressions>
目前我正在研究ptree和read_xml领域的BOOST 请告知可以找到其他信息的位置? 提前致谢
我目前的调查结果是:
我有一个定义Expression的类,它使用虚函数来计算表达式,在继承树中更低,这个函数应该被覆盖并在表达式类型的上下文中实现。
class AbstractExpression
{
public:
AbstractExpression(ExpressionType aType){}
virtual ~AbstractExpression() {}
// Evaluates expression (must be overrided by child)
virtual int evalExpr() const = 0;
};
继承的类是additionExpression
,substractionExpression
,multiplicationExpression
,divisionExpression
。
除此之外,我已经在每个继承的类中实现了数据操作方法。
最后我写了一些代码,用来计算这个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;
}
}
现在我需要将所有这些结果写入XML。
答案 0 :(得分:1)
真的,使用适当的XML库(TinyXML,RapidXML,PugiXML,libxml2等)。
如果您真的只关心XML的一个非常特定的子集,那么这里有一个快速的&amp;基于Boost Spirit V2的脏解析器: Live On Coliru
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>
<强> Live On Coliru 强>
注意:不处理注释,unicode,处理指令,命名空间,PCDATA,字符实体引用等。简而言之这不是XML解析器 < / p>