2008年9月18日木曜日

JavaでHTMLタグを除いたり閉じてないタグを閉じたり

スズキです。

表記をJavaらしく実装しようといろいろ調べたり試したりしていたら、
JAXPっぽい実装になってしまいました。

主役はNekoHTMLの
org.cyberneko.html.parsers.DOMFragmentParser
http://nekohtml.sourceforge.net/
とXercesの
org.apache.xml.serialize.XMLSerializer
http://xerces.apache.org/xerces2-j/
です。

全部じゃないですが、インポートするのはこんな感じです。

import org.apache.html.dom.HTMLDocumentImpl;
import org.apache.xerces.xni.parser.XMLDocumentFilter;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.cyberneko.html.filters.ElementRemover;
import org.cyberneko.html.filters.Purifier;
import org.cyberneko.html.parsers.DOMFragmentParser;

タグの除去をテストするメソッドです。
XMLDocumentFilterにElementRemoverを利用しています。

public void convertByRemover() throws Exception {
  String htmlFragment = "<p> あああ <p> いいい <p> ううう";
  XMLDocumentFilter[] filters = { new ElementRemover() };
  System.out.println(convertHtml(filters, htmlFragment));
}

閉じてないタグの閉じをテストするメソッドです。
XMLDocumentFilterにPurifierを利用しています。

public void convertByPurifier() throws Exception {
  String htmlFragment = "<p> あああ <p> いいい <p> ううう";
  XMLDocumentFilter[] filters = { new Purifier() };
  System.out.println(convertHtml(filters, htmlFragment));
}

つまり、XMLDocumentFilterという仕組みを使って、
与えられたHTMLをフィルタリングする形になっています。

で実際その中身は下記となります。
(結構、読みずらい...)

private String convertHtml(XMLDocumentFilter[] filters, String
htmlFragment) throws Exception {
  DOMFragmentParser parser = new DOMFragmentParser();
  // フィルターの設定
  parser.setProperty("http://cyberneko.org/html/properties/filters", filters);
  HTMLDocument document = new HTMLDocumentImpl();
  DocumentFragment fragment = document.createDocumentFragment();
  // 対象となるHTMLを設定
  InputSource inputSource = new InputSource(new StringReader(htmlFragment));
  parser.parse(inputSource, fragment);
  StringWriter writer = new StringWriter();
  OutputFormat format = new OutputFormat();
  // XML宣言は出力して欲しくない
  format.setOmitXMLDeclaration(true);
  XMLSerializer serializer = new XMLSerializer();
  serializer.setOutputCharStream(writer);
  serializer.setOutputFormat(format);
  serializer.serialize(fragment);
  return writer.getBuffer().toString();
}

結果はconvertByRemoverが

あああ いいい ううう

convertByPurifierが

<P> あああ </P><P> いいい </P><P> ううう</P>

と無事目的を達成することができました。

週末は、これらを使ったConverter(Teeda)祭りかな?

--
http://suz-lab.blogspot.com/

0 コメント: