Синтаксический анализ одного узла XML с помощью peg.js
Учитывая вход <outer> Content <inner> Inner <single/> </inner> </outer>
,
Как бы я написал грамматику, которая разбирает <single>
узел вместе с узлами, которые имеют соответствующий закрывающий узел?
Вот мой текущий грамматик, который был взят отсюда:
Content =
(Element / Text)*
Element =
startTag:StartTag content:Content endTag:EndTag {
if (startTag != endTag) {
throw new Error(
"Expected </" + startTag + "> but </" + endTag + "> found."
);
}
return {
name: startTag,
content: content
};
}
StartTag =
"<" name:TagName ">" { return name; }
EndTag =
"</" name:TagName ">" { return name; }
TagName = chars:[a-z]+ { return chars.join(""); }
Text = chars:[^<]+ { return chars.join(""); }
Это работает только с узлами, которые имеют закрывающий узел.
Я думаю, что проблема заключается в текстовом правиле. Поэтому я экспериментировал с его изменением, включив в него негативную перспективу, например:
Text = chars:(!EndTag .)* EndTag { return chars.join(""); }
Но это еще ничего не дало.
Есть идеи?
1 ответ
Я сделал так, чтобы элемент соответствовал либо sTag, либо selfTag; если он соответствует "selfTag", то нет "Content" или "endTag":
Content =
(Element / Text)*
Element =
startTag:sTag content:Content endTag:eTag {
if (startTag != endTag) {
throw new Error(
"Expected </" + startTag + "> but </" + endTag + "> found."
);
}
return {
name: startTag,
content: content
};
}
/ startTag:selfTag {
return startTag;
}
sTag =
"<" name:TagName ">" { return name; }
selfTag =
"<" name:TagName "/>" { return name; }
eTag =
"</" name:TagName ">" { return name; }
TagName = chars:[a-z-]+ { return chars.join(""); }
Text = chars:[^<]+ { return chars.join(""); }
Обратите внимание, что этот ответ требует использования <single/>
вместо <single>
(то есть / требуется); это самый простой способ сообщить анализатору PEG о разнице между висящим начальным тегом и "самозакрывающимся тегом".