右頬を殴られたら左頬を、左頬を殴られたら右頬を (nextLinkを@hrefの数値を見て大きいほうを選ぶ。しかもXPathだけでな)
TumblrのSITEINFOを@hrefの数値を見て大きいほうを選ぶって方法でなんとかできないかと試した形跡。
//a[starts-with(@href,"/page/")][1][number(substring-after(self::a/@href,"/page/")) > number(substring-after(following-sibling::a/@href,"/page/"))] | //a[starts-with(@href,"/page/")][2][number(substring-after(self::a/@href,"/page/")) > number(substring-after(preceding-sibling::a/@href,"/page/"))]こんなXPathはいや - 0x廃棄階層 - 統治局
???
解読しよー、そーしよー。しかし長いなあ。まずは適当に改行を入れてみると
//a[starts-with(@href,"/page/")][1] [ number(substring-after(self::a/@href,"/page/")) > number(substring-after(following-sibling::a/@href,"/page/")) ] | //a[starts-with(@href,"/page/")][2] [ number(substring-after(self::a/@href,"/page/")) > number(substring-after(preceding-sibling::a/@href,"/page/")) ]
たぶん、こっちが次のページへのリンクが左にある場合を表現
//a[starts-with(@href,"/page/")][1] [ number(substring-after(self::a/@href,"/page/")) > number(substring-after(following-sibling::a/@href,"/page/")) ]
そんで、こっちが次のページへのリンクが右にある場合を表現
//a[starts-with(@href,"/page/")][2] [ number(substring-after(self::a/@href,"/page/")) > number(substring-after(preceding-sibling::a/@href,"/page/")) ]
htmlだとこんなんだ。
<a href="/page/1">« Previous</a> <a href="/page/3">Next »</a>
number()ってのは知ってるぞ。XpathGraphでお世話になってるやつだ。
関数: number number(object?)
number 関数は、以下のように引数を数値に変換する。
XML Path Language (XPath)
- 空白 (オプション) に マイナス記号 (オプション) が続き、その後に Number、さらに空白が続く文字列の場合には、その文字列が表現する数学的値に (IEEE 754 の round-to-nearest ルールに従って) 最も近い IEEE 754 数値に変換する。それ以外の文字列は NaN に変換する。
substring-after()ってのも、XpathGraphでお世話になってる。
関数: string substring-after(string, string)
substring-after 関数は、2番目の引数に指定した文字列が1番目の引数に指定した文字列内で最初に見つかった場合に、その文字列よりも後にある文字列 (サブストリング) を返す。2番目の引数に指定した文字列が1番目の引数に指定した文字列内に含まれていない場合は、空の文字列を返す。 たとえば substring-after("1999/04/01","/") は 04/01 を返し、 substring-after("1999/04/01","19") は 99/04/01 を返す。
XML Path Language (XPath)
substring-after(self::a/@href,"/page/") で a href="/page/1" っていうところのページ番号をとりだして、number()でそれを数値にしてからそれぞれの大きさを比較してんだな。そんなもん括弧[]の中に入れられるんだ!!!
ほんでもって、位置の話しだ。
//a[starts-with(@href,"/page/")][1]
っていうのは上の例でいうと基準点が"Previous"っていう方だ(a href="/page/1")
そいでもって
//a[starts-with(@href,"/page/")][1]/self::node()
っていうのは基準点自身のことだからa href="/page/1"のことで
//a[starts-with(@href,"/page/")][1]/following-sibling::node()
っていうのは基準点より後にあるヤツってことだからa href="/page/3"のことだ。
ほんでもって、次なのだが
//a[starts-with(@href,"/page/")][2]
っていうのは上の例でいうと基準点が"Next"っていう方だ(a href="/page/3")
そいでもって
//a[starts-with(@href,"/page/")][2]/self::node()
っていうのは基準点自身のことだからa href="/page/3"のことで
//a[starts-with(@href,"/page/")][2]/preceding-sibling::node()
っていうのは基準点より前にあるヤツってことだからa href="/page/1"のことだ。
# following-sibling::chapter[position()=1] はコンテキストノードの次の chapter という名前の兄弟エレメントを選択する。
# preceding-sibling::chapter[position()=1] はコンテキストノードの前の chapter という名前の兄弟エレメントを選択する。
XML Path Language (XPath)
あーだんだんわかってきたぞ。
しまった、前提条件を説明してなかった。
実は、tumblrって公式テーマみたいなのがあってそれを自由に選べるんですが、そいつのnextLinkがですねー、右にあったり左にあったりするんです。
2008-05-07 - 天下泰平 The Whole World is peaceful.
ということなのです。上の写真で示した例だと"next"だから右側が次のページになるんだ。
あー面倒になってきたが、なんとなくわかってきたよ。いつもながらスゴイね。id:os0x!!!! これって汎用性高いんじゃないのか? ねエ? (効率の話しがつきまとうのか?)
これ貼りてえーなー。wedata.netに。ダメかなあ。
追記:
1ページ目がだめだった。つまり次のページへのリンクが一個しかないとき。
2ページ目から(Last - 1)ページ目まではこのnextLinkでおkだけど、1ページ目とLastページ目のことを考えないとダメだ。
Lastページでの逆流を許すなら(a[last()]とおなじレベル)なら1ページ目のリンクが一個しかないときの対応だけなのでシンプルにいけそうだけど。こんなかんじかなあ。
//a[starts-with(@href,"/page/")][1][not(following-sibling::a)]
っていう1ページ目の表現を追加して、
//a[starts-with(@href,"/page/")][1][not(following-sibling::a)] | //a[starts-with(@href,"/page/")][1][number(substring-after(self::a/@href,"/page/")) > number(substring-after(following-sibling::a/@href,"/page/"))] | //a[starts-with(@href,"/page/")][2][number(substring-after(self::a/@href,"/page/")) > number(substring-after(preceding-sibling::a/@href,"/page/"))]
で、整理すると、
//a[starts-with(@href,"/page/")][1][not(following-sibling::a) or (number(substring-after(self::a/@href,"/page/")) > number(substring-after(following-sibling::a/@href,"/page/")))] | //a[starts-with(@href,"/page/")][2][number(substring-after(self::a/@href,"/page/")) > number(substring-after(preceding-sibling::a/@href,"/page/"))]
ってなるんだけど、まとめちゃうとメンテナンスしずらいかなあ。