手动快速解析文件变得很棘手。您可能想看看递归下降解析器。
它是一种模式,它通过让函数以递归方式解码每个元素来实现文件的语法。
让我们用一个简化的 XML 语法(BNF 形式)举一个简单的例子:
element ::= '<'<tag>'/>'|'<'<tag>'>'<content>'<'<tag>'/>'
content ::= <element>|<freetext>|<freetext><element>
freetext ::= [^<>]<freetext>
tag ::= <alpha>|<alpha><alphanum>
alpha ::= [a-zA-Z]
alphanum ::= [a-zA-Z0-9]
(我认为正则[...]
表达式的语法不是 BNF 的一部分,但对我来说它比写下所有字母更简单:-)[^<]
表示任何不是 < 的字符都会与 XML 中标记的开头冲突)
该语法描述了一个元素。一个元素由一个自闭合标签(例如:)<br/>
或一个开始标签,后跟一个内容,然后是一个结束标签组成。内容可以是一个元素(因此使用前一个元素递归定义)、一些自由文本或一些自由文本后跟一个元素。ETC ...
然后可以机械地实现解析:
Element parse_element(char *c)
{
Element myElement; // Element contains the result of the parsing
// It's a type you have to define !
assert( *c == '<' ); // Handle the error in a more clever way :-)
c++;
Tag myTag = parse_tag(c);
if( *c == '/')
{
// Self-closing tag - add myTag to myElement
c++;
assert( *c == '>'); // Here again, better error handling
c++;
}
else
{
// Or a start tag
assert( *c == '>'); // Here again, better error handling
c++;
Content myContent = parse_content(c);
// Add myTag with myContent to myElement
assert( *c == '/'); // Here again, better error handling
c++;
assert( *c == '>'); // Here again, better error handling
c++;
}
return myElement;
}
我希望这个功能足以了解这个概念。要理解的要点是,您首先需要对要阅读的格式有一个清晰的语法定义。然后,您可以机械地实现解析器。
请注意,此示例太简单了:您至少需要处理实体、属性等...才能解析真正的 XML。
一旦你掌握了语法,一些工具,如GNU Bison ,就可以简化代码的编写。
最后,如评论中所述,如果您想解析 XML 文件,则存在一些像libxml这样的 XML 解析器。这将比实现自己的解析器更容易和更完整。XML 是一种非常复杂的格式。