2008/4/22 火曜日 by kouichi
なにげにJavaDocを見ていたらDomQueryというものがありました。
JavaScriptでXPath的なものが使えるようです。
例えば、
HTML上のdivエレメントを取得
Element[] el = DomQuery.select("div");
IDがxxx以下のdivエレメントを取得
Element[] el = DomQuery.select("div",RootPanel.get("xxx"));
classがxyzのdivを取得
Element[] el = DomQuery.select("div[@class='xyz']");
など。
複雑な式は使えないようですが、なかなか面白いです。
classやIDのprefixからエレメントを取得するなどができるようになるので結構便利だと思います。
Posted in GWT, xpath | No Comments
2008/2/4 月曜日 by kouichi
以前xsltを使っていたこともあって、Xpathにはなじみがあったのですが、JavaのDOM操作でもXpathはなかなか使い勝手が良かったです。
特に今はHTMLをパースすることが必要なので重宝しています。
例えば、HTMLからdescriptionの文字列取得を、DOM操作で行うと
NodeList metaList = document.getElementsByTagName("meta");
for(int i=0;i<Element element = (Element)metaList.item(i);
String name =element.getAttribute("name");
if(!OkStringUtil.isNullEmpty(name)&&name.toLowerCase().equals("description")){
description = element.getAttribute("content");
continue;
}}
のようなコードになると思います。
これが、Xpathを使うと、
Node description = XPathAPI.selectSingleNode(doc, "//META[translate(@name, 'DESCRIPTION', 'description')='description']/@content");
と1行。
他にも
NodeList list = XPathAPI.selectNodeList(doc, "//*/text()");
とかでHTML内のテキスト要素をすべて取得できます。
しかもコメント部分が省かれているのでさらに良い。
NodeList list = XPathAPI.selectNodeList(doc, "//A/@href");
でアンカーのリンクだけ取得できます。
すばらしい。
Posted in xpath | No Comments
2008/2/3 日曜日 by kouichi
公開されいてるHTMLは整形されたものばかりではないので、クロールして解析するには整形する必要があります。
Javaではnekohtmlというライブラリがありますので、そちらを使ってみました。→ダウンロードはこちら
なお、これをつかうにはxerces2のライブラリも必要です。→ダウンロードはこちら
HTMLソースからアンカーだけ取得するサンプルを作りました。
public static void main(String[] args) throws Exception{
DOMParser parser = new DOMParser();
parser.parse(args[0]);
Node node = parser.getDocument();
NodeList list = XPathAPI.selectNodeList(node, "//A");
for(int i=0;i>list.getLength();i++){
Element element = (Element)list.item(i);
System.out.println(element.getTextContent() + " / " + element.getAttribute("href"));
}}
とかでOK。結構簡単です。
HTMLの読み込みとパースは
DOMParser parser = new DOMParser();
parser.parse(args[0]);
Node node = parser.getDocument();
の部分です。
(以前は違ったと思うのですが)、HTTPヘッダのContetTypeにcharsetを指定してないHTMLでも文字コードを判断してパースしてくれるようで、文字コードを使う側で判別しなくてもOKなのでかなり便利です。
NodeList list = XPathAPI.selectNodeList(node, "//A");
の部分は
NodeList list = ((Document)node).getElementsByTagName("a")
とかでもOKなのですが、せっかくなのでXpathを使ってみようと思います。
xpathの指定では”//a”ではダメで、”//A”と大文字で指定する必要がありますので要注意です。
これで確認していたところ、http://ameblo.jp/がパースできないことが判明。
どうも、
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
のようにNSを指定しているとだめらしく、この場合は
DOMParser parser = new DOMParser();
parser.setFeature("http://xml.org/sax/features/namespaces", false);
parser.parse(args[0]);
Node node = parser.getDocument();
のように、namespaseの機能を追加する必要がありました。
ちなみにソースはこちら→ダウンロード
Posted in xpath | 1 Comment