青空文庫のXMLは仕様通りにキッチリ書いてあるものと、そうでないものがあり、ちょっと苦労した。
以下のクラスは基本的に「大見出し」と「中見出し」で区切って配列にして返すものだけど、面倒な処理は正規表現やexplodeでばっさり切り分けたりしてます。
---
このクラスを使って小説を転載したものは、以下のサイトで読めます。
・多賀城[たがのき]小説投稿サイト
良かったら見てくださいませ。
---
/* * 青空文庫XMLパーサ * 2013/10/01 */ class Aozora { const FROM_ENCODING = 'sjis-win'; const TO_ENCODING = 'UTF-8'; public $filename; public $title; public $author; /* 本文の階層構造 大見出しがある場合 bodies = array( '大見出し_01' => array( '中見出し_01' => '本文', '中見出し_02' => '本文', ... '中見出し_nn' => '本文' ), '大見出し_02' => array( '中見出し_01' => '本文', '中見出し_02' => '本文', ... '中見出し_nn' => '本文' ), '大見出し_03' => array( '中見出し_01' => '本文', '中見出し_02' => '本文', ... '中見出し_nn' => '本文' ), ... '大見出し_nn' => array( '中見出し_01' => '本文', '中見出し_02' => '本文', ... '中見出し_nn' => '本文' ) ); 大見出しが無い場合 bodies = array( '中見出し_01' => '本文', '中見出し_02' => '本文', ... '中見出し_nn' => '本文' ); */ public $bodies; public $infomation; // 小説情報 public $notes; // 注 public $is_omidasi; public $is_tyumidasi; private $raw_text; private $main_text; private $biblio; public function __construct( $filename ) { $this->filename = $filename; $this->raw_text = file_get_contents( $this->filename ); $this->raw_text = mb_convert_encoding( $this->raw_text, self::TO_ENCODING, self::FROM_ENCODING ); $this->bodies = array(); } public function get_title() { return sprintf( '%s (作者:%s)', $this->title, $this->author ); } public function get_bodies() { return $this->bodies; } /** XMLパース本体 */ public function parse() { // 改行を全て消す $this->raw_text = preg_replace( '#[\n\r]+#i', '', $this->raw_text ); $this->raw_text = preg_replace( '#[\s]+#i', ' ', $this->raw_text ); // タイトルと著者を取得する $ret = preg_match( '#(.*?)
#i', $this->raw_text, $temp_text ); $this->title = $this->replace_imgtag( $temp_text[ 1 ] ); $this->title = trim( $this->title ); $ret = preg_match( '#(.*?)
#i', $this->raw_text, $temp_text ); $this->author = $this->replace_imgtag( $temp_text[ 1 ] ); $this->author = trim( $this->author ); // 付加情報を取得する $ret = preg_match( '#(.*?)#i', $this->raw_text, $temp_text ); $this->infomation = $this->remove_htmltag( $temp_text[ 1 ] ); $this->infomation = $this->add_return( $this->infomation ); $this->infomation = trim( $this->infomation ); // 本文を全て取得する $ret = preg_match( '#(.*)#i', $this->raw_text, $temp_text ); $this->main_text = trim( $temp_text[ 1 ] ); // 大見出しから切り出し $this->parse_omidasi(); } /* 大見出しがある場合の本文切り出し */ private function parse_omidasi() { if( $this->is_omidasi( $this->main_text ) ) { // 大見出しがある場合 $temp_text = explode( '', $this->main_text ); foreach( $temp_text AS $temp ) { if( trim( $temp ) == "" ) { continue; } if( !$this->is_omidasi( $temp ) ) { continue; } $ret = preg_match( '#(.*?)
(.*)$#', $temp, $temp_omidasi ); $omidasi = $this->remove_htmltag( $temp_omidasi[ 1 ] ); $omidasi = $this->replace_imgtag( $omidasi ); $omidasi = trim( $omidasi ); $this->bodies[ $omidasi ] = $this->parse_tyumidasi( $temp_omidasi[ 2 ] ); } } else { // 大見出しがない場合 $this->bodies[] = $this->parse_tyumidasi( $this->main_text ); } } /* 中見出しから本文切り出し @param $html 大見出し1つ分のテキスト または 本文全体のテキスト */ private function parse_tyumidasi( $html ) { $tyumidasi_array = array(); if( $this->is_tyumidasi( $html ) ) { $temp_text = explode( '', $html ); foreach( $temp_text AS $idx => $temp ) { if( trim( $temp ) == "" ) { continue; } if( !$this->is_tyumidasi( $temp ) ) { continue; } $ret = preg_match( '#(.*?)
(.*)$#', $temp, $temp_tyumidasi ); $tyumidasi = $this->remove_htmltag( $temp_tyumidasi[ 1 ] ); $tyumidasi = $this->replace_imgtag( $tyumidasi ); $tyumidasi = trim( $tyumidasi ); $tyumidasi_array[ $tyumidasi ] = $this->remove_htmltag( $temp_tyumidasi[ 2 ] ); $tyumidasi_array[ $tyumidasi ] = $this->replace_imgtag( $tyumidasi_array[ $tyumidasi ] ); $tyumidasi_array[ $tyumidasi ] = $this->add_return( $tyumidasi_array[ $tyumidasi ] ); } } else { $tyumidasi_array[ 1 ] = $this->remove_htmltag( $html ); $tyumidasi_array[ 1 ] = $this->replace_imgtag( $tyumidasi_array[ 1 ] ); $tyumidasi_array[ 1 ] = $this->add_return( $tyumidasi_array[ 1 ] ); } return $tyumidasi_array; } /* 大見出しがあるかどうか */ private function is_omidasi( $html ) { $ret = substr_count( $html, '' ); if( $ret > 0 ) { $this->is_omidasi = true; } else { $this->is_omidasi = false; } return $this->is_omidasi; } /* 中見出しがあるかどうか */ private function is_tyumidasi( $html ) { $ret = substr_count( $html, '' ); if( $ret > 0 ) { $this->is_tyumidasi = true; } else { $this->is_tyumidasi = false; } return $this->is_tyumidasi; } /* 余分なHTMLタグを除去する */ private function remove_htmltag( $text ) { return preg_replace( '#<(?:|/)(?:em|div|span|a|h3|h4|hr)[^>]*>#', '', $text ); } /* 画像タグを置き換える */ private function replace_imgtag( $text ) { return preg_replace( '#]+>#', "$1", $text ); } /* * 改行を元に戻す */ private function add_return( $text ) { return preg_replace( '#
]+>#', "\r\n", $text ); } }
以上です。