Skip to content

Instantly share code, notes, and snippets.

@fumikito
Created October 16, 2010 14:42
Show Gist options
  • Save fumikito/629847 to your computer and use it in GitHub Desktop.
Save fumikito/629847 to your computer and use it in GitHub Desktop.
HTMLのpタグにインテルを挿入する
<?php
/**
* XMLの特定のタグにインテルを挿入する
*
* インテルとは活版印刷で用いられる活字間の隙間を挿入する金属のことです。
* Webkitエンジンなど、CSSのtext-justifyプロパティに対応していないブラウザは
* テキストのジャスティフィケーションを半角スペースのサイズ調整で行います。
* 日本語は分かち書きをしないため、半角スペースでのサイズ調整が適用されません。
* このクラスでは指定されたタグの直下にあるすべてのテキストのノードに対して
* 空白を含むspanタグを挿入します。
* 現在ではePubに用いるxhtml1.0にのみ対応しています。
*
* PHP versions 5
*
* @package Hametuha/DOM
* @author   Takahashi Fumiki <[email protected]>
* @license   http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version   0.1
*/
class Intel
{
/**
* 直後での改行を許さない禁則文字のリスト
*
* @var string
*/
private static $_disallow_after = "「【《";
/**
* 直前に改行を許さない禁則文字のリスト
*
* @var string
*/
private static $_disallow_before = "a-zA-Z0-9., \-_ 。、ー・/?!」】》]〕…—ーっぁぃぅぇぉゃゅょッァィゥェォャュョヶ々ゞ";
private static $_css = "span.intel{}";
/**
* 渡されたXML文字列にインテルを挿入する
*
* @param string $content
* @param strin g$tag
* @return string
*/
public static function insert($content, $tag)
{
$xml = new DOMDocument();
$xml->validateOnParse = true;
if($xml->loadXML($content)){
self::_iterate($xml, $tag);
return self::_clean($xml->saveXML());
}else
return false;
}
/**
* 指定されたファイルにインテルを挿入して保存する
*
* @param string $path
* @param string $tag
* @return boolean
*/
public static function insertToFile($path, $tag)
{
if(!is_file($path) || !is_writable($path))
return false;
$xml = new DOMDocument();
$xml->validateOnParse = true;
if($xml->load($path)){
self::_iterate($xml, $tag);
return file_put_contents( $path, self::_clean( $xml->saveXML() ) );
}else
return false;
}
/**
* 特定のタグに対して反復処理を行う
*
* @param DOMDocument $xml
* @param string $tag
* @return void
*/
private static function _iterate($xml, $tag)
{
//対象となるタグを取得
$parents = $xml->getElementsByTagName($tag);
//すべてのタグに対して処理を行う
for($i = 0, $l = $parents->length; $i < $l; $i++){
//データ保存用のノードを作成
$newParent = $parents->item($i)->cloneNode(false);
//対象ノードのすべての子要素に処理を行う
foreach($parents->item($i)->childNodes as $node){
//テキストノードだったら
if($node->nodeName == "#text"){
//テキストの配列を作成
$str = self::str_split($node->nodeValue);
//新しいノードを作る
for($j = 0, $k = count($str) - 1; $j < $k; $j++){
//テキストノードを追加
$newParent->appendChild($xml->createTextNode($str[$j]));
//次にインテルを挿入可能ならば挿入する
if(preg_match("/[^".self::$_disallow_after."]/u", $str[$j]) && preg_match("/[^".self::$_disallow_before."]/u", $str[$j + 1])){
$intel = $xml->createElement("span");
$intel->setAttribute("class", "intel");
$intel->appendChild($xml->createTextNode(" "));
$newParent->appendChild($intel);
}
}
}
//違ったらコピーしてそのまま追加
else{
$newParent->appendChild($node->cloneNode(true));
}
}
//新しいタグを入れ替える
$parents->item($i)->parentNode->replaceChild($newParent, $parents->item($i));
}
}
/**
* 特定の文字列を削除する
*
* @param string $xml_string
* @param string $delete
* @return
*/
private static function _clean($xml_string, $delete = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
{
return str_replace($delete, "", $xml_string);
}
/**
* UTF-8の文字列に対してstr_splitを実行する
*
* @param string $string
* @param int $split_length
* @return array
* @author seebz.net
* @see http://jp2.php.net/manual/ja/function.str-split.php#97690
*/
private static function _str_split($string, $split_length = 1)
{
preg_match_all('`.`u', $string, $arr);
$arr = array_chunk($arr[0], $split_length);
$arr = array_map('implode', $arr);
return $arr;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment