BoostSpirit,如何扩展xml解析
Boost.Spirit, how to extend xml parsing?
我想使用BoostSpirit扩展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
设备,这样你就可以处理空标签了。如果我这样做,我可能会创建一个empty_tag
规则,然后将xml
更改为empty_tag | (start_tag > *node > end_tag)
。W3C语言推荐就是这样做的:
[39] element ::= EmptyElemTag
| STag content ETag
但现在不用担心。请记住,您指定的任务是将属性添加到解析器中。不要被其他缺失的功能分散注意力。以后还有很多工作要做。
我提到了W3C文件。你应该经常提到这一点;它定义了语言,甚至显示了语法。Spirit的设计目标之一是它看起来像一个语法定义。通过尝试在自己的代码中模仿W3C语法来利用这一点。W3C定义的起始标签如下:
[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属性是另一回事(这样你就可以在程序的其余部分中知道给定标签的属性名称和值),我现在不准备讨论这个问题。
- Cppcheck生成xml转储文件
- 是否可以通过C++扩展强制多个python进程共享同一内存
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 扩展光电二极管探测器以支持多个传感器
- 如何在pugixml中获取节点的内部XML
- 如何使用tinyxml2从XML加载父实体和子实体
- C++中的VLA,扩展名为std=C++11
- boost xml parsingl将xml的路径作为变量发送
- OpenGL 和 GLM 矩阵无法正确扩展,总是按比例缩小
- C++RapidXml-使用first_node()遍历以修改XML文件中节点的值
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用 Tinyxml 在 xml 中添加一个子子项
- C++返回 Numpy 数组的 Python 扩展模块
- 扩展可变参数模板中的变量名称
- 增强基于 XML class_id的反序列化
- 扩展C++生成的代码的模板参数类型名称
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- VSCode IntelliSense无法识别SDL框架的SDL_image扩展库
- BoostSpirit,如何扩展xml解析