使用peg.js解析XML单节点

时间:2014-09-28 21:40:08

标签: javascript xml peg

给出输入<outer> Content <inner> Inner <single/> </inner> </outer>

我如何编写解析<single>节点的语法以及具有匹配结束节点的节点?

这是我目前的语法,取自here

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规则。因此,我一直在尝试改变它,以包括一个负面的前瞻,如:

Text    = chars:(!EndTag .)* EndTag { return chars.join(""); }

但那还没有取得任何成功。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我这样做的方法是让Element匹配为“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解析器发出悬挂起始标签和“自闭标签”之间差异的最简单方法。