DOM

この投稿は1年半前の記事です。 情報が古くなっている可能性があるので、その点ご了承ください。
2015 年 4 月 13 日 716日前)
2,715文字 (読了時間6分)

SPONSORED LINK

タイトルそのままですが、現在破滅派では、ePub書き出し機能を製作中で、ePub書き出し機能自体はできたのですが、また別の問題が発生しました。

たとえば、僕は方舟謝肉祭という長編小説を発表しているのですが……

  • 連載作品だった場合、ePubで売っているのにWebで全部読めてしまうのは困るので、途中で隠したい。
  • その際、全部統一したやり方で隠したい。抜粋( excerpt ) めんどくさいから入れたくない。

破滅派では何も考えずに書くとpタグが連続する感じになるので、タグの数を数えてその4分の1だけ表示するという方針でいきます。n話までは無料で読めて、あとは途中までしか読めないというパターンですね。

さて、DOMるときに使うライブラリはHTML5-PHPです。HTML5だとbrなどの空タグにスラッシュがあってもなくてもよいからパースエラーになったりとか、DOMDocumentだと日本語が全部実体参照になるとか、そういうどうしようもないエラーが回避できます。

このライブラリ、単に読み込みと書き出しがHTML5対応になっているだけっぽいので、あとはDOMDocumentと同じです。

それでは、the_contentフィルターをかけてみます。ポイントは次の通りですね。

  1. the_contentでわたってくるタグは親ノードがないので、htmlタグを擬似的に作成する。
  2. 書き出しのとき、bodyタグの中身だけ返す
  3. ショートコードとかwpautopとかに影響を受けないように、一番最後の方にフィルター。
add_filter('the_content', function($content){
    if( sold_in_amazon() ){ // 独自関数なのでコピペしないでね!
         // パーサーを用意
         $html5 = new Masterminds\HTML5();
         // HTMLを作る
         $html = <<<HTML
<DOCTYPE html>
<html>
<head><meta charset="utf-8" /></head>
<body>{$content}</body>
</html>
HTML;
         // DOMの一部を切り出す
         $dom = $html5->loadHTML($content);
         // bodyタグを取得
         $body = $dom->getElementsByTagName('body')->item(0);
         // bodyタグの子ノードを数える
         $dom_count = $body->childNodes->length;
         // その4分の1の数を取得
         $limit = floor( $dom_count / 4 );
         // 1/4より大きいノードは削除
         for( $i = $dom_count - 1; $i >= 0; $i-- ){
             if( $i > $limit ){
                  $body->removeChild($body->childNodes->item($i));
             }
         }
         // bodyタグの中身だけ取得して$contentに設定
         preg_match('/<body>(.*)<\/body>/s', $html5->saveHTML($dom), $match);
         $content = $match[1];
    }
    return $content;
}, 9999);

というわけで、このお尻にメッセージボックスを足したりすると、こんな感じになります。ぱっと見わからないので、デザインに工夫の余地ありかもですね……透明のフィルターっぽいのかぶせるとか。

本文が途中までしか表示されなくなる
本文が途中までしか表示されなくなる

DOMの何がいいかというと、堅牢性です。「すぐパースエラーになるのに堅牢もクソもあるか」という向きもあるでしょうが、属性値を変えたりとか、そういう操作は正規表現や文字列置換でやるとぶっ壊れる可能性があるので、DOMだと安心です。

以前、WordBenchで「h3タグの1つ目の前にAdsenseタグ入れる」というプラグインを作っている方もいましたが、そういう場合なんかはDOMると楽ですね。

XPathとも一緒に使えるので、フィルタリングも可能なはず。ただし、XPathを覚えないといけないという別の罠があるんですけどね。

注意点としては、DOMるときのコストが結構高いこと。シングルページだと一回だけだからいいですけど、ループの中で使ったりするとかなり計算負荷が高いです。目に見えて遅くなるでしょうね。

DOMにもいろいろあって、BehatとかのおまけについてくるDOMパーサーは軽量らしいですね。

というわけで、よく考えたらWordPressじゃなくてPHP全般の話だったんですけど、終わります。

10日でおぼえるXML入門教室 第2版

10日でおぼえるXML入門教室 第2版 [書籍]

著者山田 祥寛

出版社翔泳社

出版日2004 年 10 月 2 日

商品カテゴリー大型本

ページ数297

ISBN4798104876

この本昔読んだんですけど、XMLだけ読んでもなにも完成しないんですよね……

Supported by amazon Product Advertising API

 

フォローしてください

ここで会ったのもなにかの縁。
高橋文樹.comの最新情報を見逃さないためにもフォローをお願いします。
めったに送らないメルマガもあります。

SPONSORED LINK

この記事について

この記事はが2015 年 4 月 13 日にプログラミングの記事として公開しました。

高橋先生の電子書籍

高橋先生の電子書籍

Amazonで電子書籍も買えます。

好きな言葉

私にはポルノの定義はできないが、見ればわかる。

— ジャレド・ダイアモンド

高橋先生の処女作

『途中下車』高橋文樹

2001年幻冬舎NET学生文学大賞受賞作です。

Web制作やります

Web制作やります

Web制作のご依頼は株式会社破滅派へ

不定期メルマガ

高橋文樹.comでは、不定期でニュースレターを配信しています。滅多に送らないので是非購読してください。

高橋文樹.comではプライバシーポリシーに準じて登録情報を取り扱います。