PowerCMS X ブログ
2024-12-10
PowerCMS Xのデータ移行処理や やさしい日本語関連の処理等で PHPの DomDocument を使うことが多いのですが、querySelector / querySelectorAll が使えず、 jQueryの find相当の処理などもできないので、自前で書くしかありませんでした。PHP8.4で querySelector / querySelectorAll がようやくサポートされ、HTML5 ドキュメントもパースできるようになりました。
新しい DOM API では、標準に沿った HTML5 ドキュメントのパース機能が追加され、古くからある標準に準拠しない複数の DOM 機能の振る舞いに関する不具合が修正され、ドキュメントの操作がより便利になるいくつかの関数が追加されました。
ありがたいですね。でも、今すぐ使いたい、PHP8.2でも使いたい、PowerCMS Xとしてもサポートしたい、ということで DomDocument と DOMElementを拡張したクラスを作成しました。継承しているので、DomDocument / DOMElement のメソッドなどは基本的にそのまま使えます次回のバージョンアップ時に lib/Prototype/ 配下に追加されます)。
ライブラリPhpGt/CssXPathが必要です。
PhpGt/CssXPath [Translator CSS selectors to XPath queries]
DomDocumentを拡張したクラス
文字列から HTML を読み込む (先頭のBOMを削除してHTMLエンティティに変換して読み込む)
ファイルから HTML を読み込む
内部のドキュメントを HTML 形式の文字列として出力する
$node が省略された時 HTMLエンティティをオリジナルのテキストに変換しなおす
指定されたクラス名をすべて持つすべての子要素の DOMNodeList を返す
指定されたセレクターまたはセレクター群に一致する、文書内の最初の PTDOMElement を返す
指定されたセレクターまたはセレクター群に一致する、文書内のすべての要素の DOMNodeList を返す
指定された $xpath に一致する、文書内のすべての要素の DOMNodeList を返す
指定されたセレクターまたはセレクター群を Xpath に変換した文字列を返す
DOMElementを拡張したクラス
要素内の HTML 文字列
要素とその子孫を含む部分の HTML 文字列 (読み取りのみ)
要素配下のすべての PTDOMElement の PTDOMNodeList (読み取りのみ)
指定されたセレクターまたはセレクター群に一致する、要素内のすべての要素の PTDOMNodeList を返す
要素の「直後」にあたる兄弟要素を返す
要素の「直前」にあたる兄弟要素を返す
要素の兄弟要素の PTDOMNodeList を返す ( $self = 自分自身を含む | 含まない )
要素の兄弟要素のうち要素の「後」に出現する PTDOMNodeList を返す
要素の兄弟要素のうち要素の「前」に出現する PTDOMNodeList を返す
要素内の HTML を返す
$html を指定した場合は要素内の HTML をセットする
要素とその子孫を含む部分の HTML 文字列を返す
指定されたクラス名をすべて持つすべての子孫要素の PTDOMNodeList を返す
要素配下のすべての子孫要素 (PTDOMElement) の PTDOMNodeList を返す
PTDOMElement オブジェクトのリスト
リスト内のノードの数
リストにあるノードの数を取得する
インデックスで指定したノードを取得する
PowerCMS Xサイトの 事例紹介 https://powercmsx.jp/cases/index.html から HTMLを取得して JSON形式で返却するサンプルコードです。
<?php
require_once( '/path/to/class.PTDomDocument.php' );
require_once( '/path/to/Translator.php' );
$dom = new PTDomDocument();
$url = 'https://powercmsx.jp/cases/index.html';
$dom->loadHTMLFile( $url );
$json = [];
$basicInfo = $dom->querySelectorAll( '.basicInfo' );
// $basicInfo = $dom->getElementsByClassName( 'basicInfo' );
foreach ( $basicInfo as $info ) {
$anchor = $info->find( 'h2 a' )->item( 0 );
$company = $anchor->innerHTML;
$link = $anchor->getAttribute( 'href' );
$text = $info->find( 'h3 + p' )->item( 0 )->innerHTML;
$subtitle = $info->find( 'h3 a' )->item( 0 )->innerHTML;
$img = $info->find( 'img' )->item( 0 );
$thumbnail = ['src' => $img->getAttribute( 'src' ), 'alt' => $img->getAttribute( 'alt' )];
$json[] = ['company' => $company,
'subtitle' => $subtitle,
'url' => $link,
'text' => $text,
'thumbnail' => $thumbnail,
];
}
header( 'Content-type: application/json; charset=UTF-8' );
echo json_encode( $json, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT );
カテゴリー:技術情報
投稿者:Junnama Noda