LoginSignup
16
14

More than 5 years have passed since last update.

JavaでHTML5をDOMパースしてXPATHを使えるようにする - Validator.nu HTML Parser

Posted at

HTML5ではタグを閉じなくてもよいのでjava.xmlのDocumentBuilderでそのままパースできません。
Validator.nu HTML Parserを利用するのが一番簡単です。

日本語のドキュメントが少ないのでメモを共有します。

このライブラリはFirefox4系のコアでC++にコード変換して利用されているとのことでかなり信頼性が高いと考えられます。これまでに数百のサイトのhtmlを解析してみましたがパースでエラーが出たことはまだありません。英語のドキュメントでの利用方法もそれなりに充実しています。
本投稿時点でのバージョンは1.4です。

使い方

まずは上記URLにあるzipをダウンロードしhtmlparser-1.4.jarにビルドパスを通します。
nu.validator.htmlparser.dom.DocumentBuilderクラスを利用することで簡単にorg.w3c.Documentに変換できます。

文字列bodyをパースするサンプル

    // Validator.nu HTMLParser付属のHtmlDocumentBuilderでパース
    HtmlDocumentBuilder builder = new HtmlDocumentBuilder();
    StringReader reader = new StringReader(body);
    Document doc = builder.parse(new InputSource(reader));

    // XPathの準備
    XPathFactory factory = XPathFactory.newInstance();
    XPath xpath = factory.newXPath();

    // XPathでid=foo要素直下の文字列を取得
    String path = "//*[@id='foo']/text()";
    String fooString = xpath.evaluate(path,doc);
    System.out.println(fooString);

    // XPathでid=var要素をw3c.dom.Nodeとして取得
    path = "//*[@id='var']";
    Node node = (Node) xpath.evaluate(path,doc, XPathConstants.NODE);

XPathの利用方法の詳細は触れません。

既知の問題?

下記のHTMLの文字列を正確に取得できません。

ソース
  <div id="foo">
    hoge A
    <div class="large">large B</div>
    foo C
  </div>

上記HTMLではXPath仕様で私の理解ではtext()で直下の文字列[hoge A foo C]が取得できるべきと思うのですが「hoge A」しか取得できません。(間違っていたらご指摘ください。)

16
14
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14