对于基于事件的解析器,用户需要向其传递一些函数(startNode(name,attrs)、endNode(name) 和 someText(txt) 可能通过接口)并在传递文件时在需要时调用它们
解析器将有一个 while 循环,该循环将在读取到 < 和直到 > 之间交替,并正确转换为参数类型
void parse(EventParser p, File file){
string str;
while((str = file.readln('<')).length !=0){
//not using a rewritable buffer to take advantage of slicing
//but it's a quick conversion to a implementation with a rewritable buffer though
if(str.length>1)p.someText(str.chomp('<'));
str = file.readln('>');
str = str.chomp('>');
//split str in name and attrs
auto parts = str.split();
string name = parts[0];
string[string] attrs;
foreach(attribute;parts[1..$]){
auto splitAtrr = attribute.split("=");
attrs[splitAtrr[0]] = splitAtrr[1];
}
if(str[0] == '/')p.endNode(name);
else {
p.startNode(name,attrs);
if(str[str.length-1]=='/')p.endNode(name);//self closing tag
}
}
}
您可以在基于事件的解析器之上构建 DOM 解析器,每个节点所需的基本功能是 getChildren 和 getParent getName 和 getAttributes(构建时使用 setter ;))
具有上述方法的 dom 解析器的对象:
class DOMEventParser : EventParser{
DOMNode current = new RootNode();
overrides void startNode(string name,string[string] attrs){
DOMNode tmp = new ElementNode(current,name,attrs);
current.appendChild(tmp);
current = tmp;
}
overrides void endNode(string name){
asser(name == current.name);
current = current.parent;
}
overrides void someText(string txt){
current.appendChild(new TextNode(txt));
}
}
当解析结束时,rootnode 将拥有 DOM 树的根
注意:我没有放任何验证码以确保xml的正确性
编辑:属性的解析有一个错误,而不是在空格上拆分,正则表达式更好