我在XMLStreamReader文档中找不到任何peek
或unread
函数。例如,为了解析HTML元素列表中的子元素列表,至少要获得一个令牌的首选方法是什么?
<ul>
<li>
<li>
</ul>
当我使用ul
和li
的解析函数创建一个递归的正确解析器时,li
解析函数必须在找到ul
的结束标记时终止,但是它不能使用它,因为ul
解析函数需要它才能成功。
我习惯用peek
或unread
来解决这些问题,但似乎缺少这些问题。解决此问题的首选Java方法是什么?
更新:我使用XMLStreamReader实现了解析器而没有预见。
答案 0 :(得分:2)
有一种实现递归解析器的常用方法,通过预先读取下一个令牌,存储它并对其进行测试,避免了对unread
或peek
的需求:
<li>
和</ul>
)实际上,你已经已经向前看。
Dragon编译器书的第1版有一个很好的例子,在他们的早期概述章节中,在C中(他们在第二版中使用Java,但它不必要地夸大其词,恕我直言 - C风格在Java中运行良好)
我将尝试从我自己的源代码中提取示例,但我的代码被分成一个库层,其中的处理方法更易于使用。我会尝试将它们结合起来做一个明确的例子,但它可能不会独立运行。把它想象成伪代码,来说明这个想法,你需要填补空白。
XMLStreamReader in;
int token;
String localname;
public void parse() {
next();
if (token==START_ELEMENT && localname.equals("ul")) ul();
}
void ul() {
next(); // assume we are called when a <ul> is seen, so we consume it
while (true) { // loops for list
if (token==START_ELEMENT && localname.equals("li")) li(); // ifs for choice
else if (token==START_ELEMENT && localname.equals("sometag")) sometag();
else break;
}
if (token==END_ELEMENT && localname.equals("ul")) next();
else throw new RuntimeException("expected </ul>");
// <li> or <sometag> would also be acceptable
}
void li() {
next();
...
}
void next() {
token = in.next(); // consume the token means to set up the next one
localname = in.getLocalName();
}
如果您创建一个图层库来处理重复的内容,我发现它更容易使用,例如我有:
boolean startTag(String name)
只要匹配void requireStartTag(String name)
如果匹配则消耗,否则抛出异常但我认为这个例子更清晰,保持一切文字。
还有其他问题,比如跳过非元素令牌(如评论,PI等);跟踪您所在的行以获得更多有用的例外等。
答案 1 :(得分:1)
似乎没有直截了当的做法。您是否可以使用XMLEventReader来完成相同的功能?