0

XMLStreamReaderのドキュメントにpeekまたはunread関数が見つかりません。たとえば、HTMLリストのように子要素のリストを解析するために、少なくとも1つのトークンを先読みするための好ましい方法は何ですか?

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

の解析関数を使用して再帰下降パーサーを作成しulli解析li関数がの終了タグを見つけたときに解析関数を終了する必要がある場合、解析関数は成功する必要がulあるため、それを消費してはなりません。ul

私はpeekまたはでそのような問題を解決するのに慣れて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 に答える