- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用 Boost.Spirit 扩展 xml 解析,并想添加 xml 属性的解析。
这里是图书馆的例子和我的一些修改:
template <typename Iterator>
struct mini_xml_grammar
: qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
{
mini_xml_grammar()
: mini_xml_grammar::base_type(xml, "xml")
{
using qi::lit;
using qi::lexeme;
using qi::attr;
using qi::on_error;
using qi::fail;
using ascii::char_;
using ascii::string;
using ascii::alnum;
using ascii::space;
using namespace qi::labels;
using phoenix::construct;
using phoenix::val;
text %= lexeme[+(char_ - '<')];
node %= xml | text;
start_tag %=
'<'
>> !lit('/')
> lexeme[+(char_ - '>')]
> '>'
;
end_tag =
"</"
> string(_r1)
> '>'
;
xml %=
start_tag[_a = _1]
> *node
> end_tag(_a)
;
xml.name("xml");
node.name("node");
text.name("text");
start_tag.name("start_tag");
end_tag.name("end_tag");
on_error<fail>
(
xml
, std::cout
<< val("Error! Expecting ")
<< _4 // what failed?
<< val(" here: \"")
<< construct<std::string>(_3, _2) // iterators to error-pos, end
<< val("\"")
<< std::endl
);
}
qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
qi::rule<Iterator, std::string(), ascii::space_type> text;
qi::rule<Iterator, std::string(), ascii::space_type> attribute;
qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
};
我试过这个,但它没有编译错误“使用未声明的标识符‘eps’”:
xml %=
start_tag[_a = _1]
> attribute
> ( "/>" > eps
| ">" > *node > end_tag(_a)
)
;
有人知道怎么做吗?如何添加解析xml属性的能力?
最佳答案
eps
标识符与您使用的许多其他标识符一样,是在 qi
命名空间中定义的。其他人通过构造函数顶部的 using
语句进入全局命名空间。对 eps
做同样的事情:
using qi::eps;
一旦你解决了这个问题,你就会遇到一个更大的问题,即你是否正确地表示了 XML 的句法和语法。看起来你做对了。你有这个:
xml %=
start_tag[_a = _1]
> attribute
> ( "/>" > eps
| ">" > *node > end_tag(_a)
)
;
不过,这不可能是对的。属性是标签的一部分,而不是标签后面的东西。看起来你想打破 start_tag
appart 以便你可以处理空标签。如果我这样做,我可能会改为创建一个 empty_tag
规则,然后将 xml
更改为 empty_tag | (start_tag > *node > end_tag)
。就是这样the W3C language recommendation这样做:
[39] element ::= EmptyElemTag
| STag content ETag
但现在不要担心。请记住,您声明的任务是向解析器添加属性。不要因其他缺失的功能而分心。以后还有很多工作要做。
我提到了 W3C 文档。你应该经常提到它;它定义了语言,甚至显示了语法。 Spirit 的设计目标之一是它应该看起来像语法定义。通过尝试在您自己的代码中模仿 W3C 语法来利用它。 W3C defines the start tag像这样:
[40] STag ::= '<' Name (S Attribute)* S? '>'
[41] Attribute ::= Name Eq AttValue
所以这样写你的代码:
start_tag %=
// Can't use operator> for "expect" because empty_tag
// will be the same up to the final line.
'<'
>> !lit('/')
>> name
>> *attribute
>> '>'
;
name %= ...; // see below
attribute %=
name
> '='
> attribute_value
;
规范定义了属性值语法:
[10] AttValue ::= '"' ([^<&"] | Reference)* '"'
| "'" ([^<&'] | Reference)* "'"
我还不担心实体引用。与空标签一样,您当前的代码已经不支持它们,因此现在将它们添加为属性的一部分并不重要。这使得 attribute_value
易于定义:
attribute_value %=
'"' > *(char_ - char_("<&\"")) > '"'
| '\'' > *(char_ - char_("<&'")) > '\''
;
name
定义不必是任何花哨的东西。它在规范中很复杂,因为它处理完整的 Unicode 字符范围,但您可以从更简单的内容开始,然后在您弄清楚如何在整个解析器中处理 Unicode 字符时再回过头来。
name %=
lexeme[char_("a-zA-Z:_") >> *char_("-a-zA-Z0-9:_")]
;
这些更改应该允许您解析 XML 属性。 但是,将结果提取为 Spirit 属性是另一回事(这样您就可以知道程序其余部分中给定标签的属性名称和值),并且我现在不准备讨论这个问题。
关于c++ - Boost.Spirit,如何扩展xml解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9473843/
我正在将一个手写解析器迁移到 Boost.Spirit (2.5.4)。第一印象是积极的,但由于我使用的是 C++17,X3 似乎是一个非常有吸引力的选择。 幸运的是,有很多关于 X3 的可用资源:
是否可以使用 boost::spirit::qi 来解析以下内容? A_B --> (A, B) A_B_C --> (A_B, C) A_B_C_D --> (A_B_
我正在尝试解析一种类似 lisp 的语言,它具有一些通用功能的语法糖。例如,plus 函数可以写成 (+ 1 2) 或 1 + 2。我认为在尝试解释语言之前消除句法糖会显着促进解释过程,因为那样的话,
我正在尝试解析一种类似 lisp 的语言,它具有一些通用功能的语法糖。例如,plus 函数可以写成 (+ 1 2) 或 1 + 2。我认为在尝试解释语言之前消除句法糖会显着促进解释过程,因为那样的话,
我想使用解析后的值作为循环解析器的输入。 语法定义了一个 header ,它指定了以下字符串的(可变)大小。例如,假设以下字符串是某个解析器的输入。 12\r\nTest Payload 解析器应提取
我正在编写 DSL 并使用 Boost Spirit 词法分析器来标记我的输入。在我的语法中,我想要一个类似于此的规则(其中 tok 是词法分析器): header_block = tok.n
我有以下精神语法。我正在尝试在 struct myresult 中创建 AST 节点的向量使用标准 push_back(at_c(qi::_val), qi::_1)但出现编译错误(见下文)。 typ
需要为 std::pair 对象提供类型为 boost::variant 的对象的值。您将如何使用其他资源来实现这个想法?下面还有其他方法吗? struct aggr_pair_visitor
我有一个词法分析器,基于该词法分析器,我现在想创建一个使用该词法分析器生成的标记的语法。我尝试改编我发现的一些示例,现在我有一些可以编译和工作的东西至少有一点,但我的一个应该失败的测试却没有。现在我想
当我使用此 qi 语法从 Lex 接受标记时: pair %= token(ID_MARKER) >> ':' >> atom >> ',' >> atom
如何解析可能包含 double 或 int 的字符串,具体取决于是否设置了点。例如。 6.0是double类型,6是int类型。规则是 rule,skipper> r = qi::double_|qi
请帮助我诊断以下错误。我有一个简单的语法: struct json_start_elem_grammar_object : qi::grammar { json_start_elem_gramma
作为使用 Boost.Spirit 的更大语法的第一阶段,我尝试解析“true”和“false”以生成相应的 bool 值,true 和 false. 我正在使用 Spirit.Lex 对输入进行标记
我正在尝试解析一个也可以包含标识符的表达式并将每个元素推送到 std::vector 中,我想出了以下语法: #include #include #include #include name
我正在为 if 函数实现生产规则: qi::rule f_if; f_if = qi::ascii::string("if") >> qi::char_('(')
我编写了这段代码示例并期望它打印OPERATION( OPERATOR(aaa) ID(bbb) ) 但我只得到OPERATION ( OPERATOR(aaa) )反而。 result2 和 it1
我的数据定义为: std::string data("START34*23*43**"); 我的语法: "START" >> boost::spirit::hex % '*' 题: 如何解析有两颗星的
我编写了这段代码示例并期望它打印OPERATION( OPERATOR(aaa) ID(bbb) ) 但我只得到OPERATION ( OPERATOR(aaa) )反而。 result2 和 it1
我需要解析一个键值对,其中键本身是示例中的固定字符串lke'cmd'。不幸的是qi::lit没有综合属性,并且qi::char_没有解析固定的字符串。 以下代码无法编译。执行后,我需要那个result
我正在尝试编写精神规则,但我无法弄清楚这个新规则的属性是什么。 以下代码按我预期的方式工作。 #include #include #include #include #include nam
我是一名优秀的程序员,十分优秀!