0

我在XMLStreamReader文档中找不到任何peek功能unread。例如,为了解析 HTML 列表中的子元素列表,获取至少一个标记的首选方法是什么?

<ul>
  <li>
  <li>
</ul>

当我创建一个具有解析函数的递归体面解析器时,解析ul函数必须在找到结束标记时终止,但它不能使用它,因为解析函数需要它才能成功。liliulul

我习惯用peekor来解决此类问题,unread但它们似乎丢失了。解决此问题的首选 Java 方法是什么?

更新:我使用 XMLStreamReader 实现了解析器,而没有前瞻。

4

2 回答 2

2

有一种实现递归解析器的常用方法,通过预先读取下一个标记、存储它并针对它进行测试来避免对unreador的需要:peek

  • 当你读入一个令牌时,你将它存储在一个(全局)变量中。
  • 然后您只需使用您正在寻找的所有令牌(例如<li></ul>)对其进行测试
  • 当您找到正确的方法时,您调用处理该问题的方法(或继续)
  • (读取下一个令牌,“消耗”了匹配的令牌)

实际上,您已经窥视了前方。

Dragon 编译器书的第 1 版有一个很好的例子,在他们早期的概述章节中,用 C 语言(他们在第 2 版中使用了 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)如果匹配则返回 true
  • void requireStartTag(String name)如果匹配则消耗,否则抛出异常

但我认为这个例子更清楚,保持字面意思。

还有其他问题,例如跳过非元素标记(如评论、PI 等);跟踪您所在的线路以获取更多有用的例外情况等。

于 2012-10-03T17:27:34.347 回答
1

似乎没有直接的方法可以做到这一点。您是否可以使用 XMLEventReader 来完成相同的功能?

于 2012-09-24T08:26:58.883 回答