UTF-8へのコード変換

コードを変換(UTF-8へ)

ubuntu(bash)において、拡張子が .html のファイルのエンコードをEUCからUTF-8へ変換する。

find -name "*.html" | xargs nkf --overtwrite -w

文字コード

  • -j : ISO-2022-JP
  • -s : Shify-JIS
  • -e : EUC-JP
  • -w : UTF-8
  • 「charset=euc-jp」を含む行の削除

    # 3行目を削除し上書き保存する
    sed -i -e "3d" *.html
    
    # 複数行を削除する場合の例
    # 5~10行目を削除し上書き保存する
    sed -i -e "5,10d" *.html
    

    「charset=”UTF-8″」を追加

    # 3行目に追加する
    sed -i -e '3i <meta charset="utf-8">' *.html
    
    # PHPのDOMを使用する場合は次のようにする
    sed -i -e '3i <meta http-equiv="content-type" content="text/html; charset=utf-8" />' *.html
    

    Bootstrap テーブル見出しの中央配置

    Bootstrapにおける、テーブル見出しは「左上配置」になり、bootstrapを使う意味がないような気になります。
    縦・横中央揃えを指定できるようなクラスも無いようで・・・
    rowspanやcolspanでセルを結合した場合は、下の画像の通り、特にひどい状態になります。

    縦・横中央に配置するには、CSSで強制的に配置してやらないとダメなようなので、
    Firebugで要素を調査したところ、次のように設定すると改善できるようです。

    .table > tbody > tr > th,
    .table > tfoot > tr > th,
    .table > thead > tr > th {
      vertical-align: middle;
      text-align: center;
    }
    

    結果は、以下の通りになりました。

    なお、cssのセレクタでお分かりのように、tableタグはbootstrapの指定に従い次のclassを指定してください。

    <!-- table-borderedは任意です -->
    <table class="table table-bordered">
    

    名前空間付きの要素にアクセスする

    かつて、こんな投稿を公開している。

    $(xml).find('ksjc\\:PrefCd').each(function(){
    

    確かに、この方法はFirefoxでは正しい対処方法です。
    全く未確認のまま公開したものではありません。

    でも、Chromeでは未確認でした。
    今日、これがChromeでは全く動かないことが分かりました。
    今朝4時からず~っと悩み続けました。

    結論
    名前空間付き要素へのアクセス方法がブラウザ毎に異なる
    Qiitaに、この違いが記載されています。

    上記の例の場合は、次の通り書き換えます。

    $(xml).find('ksjc\\:PrefCd, PrefCd').each(function(){
    

    これで、FirefoxでもChromeでも動くようになります。
    なお、find(‘ksjc\\:PrefCd, PrefCd’)は、‘ksjc\\:PrefCd’ または ‘PrefCd’ の意です。

    <gml:Point gml:id="p1">
      <gml:pos>35.60733100 140.10638000</gml:pos>
    </gml:Point>
    

    この様な、xmlの属性 gml:id にアクセスする場合は

    $(xml).find("Point").each(function(){
      gid = ($(this).attr("gml:id");
    
    

    名前空間(gml)が必要ですので注意が要ります。

    薄明に関するメモ

    引続き、PHP日付関数から。
    twilightと言う単語が出てくるので、その定義を調べたもの。
    「トワイライト」と言うと、私の勝手なイメージからは「薄暮」と言う言葉が浮かぶのだが、
    実際は、日の出前と日の入後の「薄明」のことを言うらしい。

    以下は、国立天文台からの引用です(一部編集しています)。

    日の入り後(日の出前),しばらくは暗くならない.上空の大気が太陽光を散乱し
    て光っているためでこれを薄明という.他に日暮れ,黄昏,夜明け,黎明[れい
    めい]などとも呼ばれる.
    
    (1) 太陽の伏角[ふかく](水平線と水平線下の太陽の中心とのなす角)が6度以内
      では, 戸外での作業に差し支えない程度の明るさで,一等星が見える
      (日の入り~6度,常用薄明または市民薄明)。
    (2) 12度までは海上で水平線が認められる状態で,多くの星が見えるようになる
      (6度~12度,航海薄明)。
    (3) さらに太陽が低くなり伏角が18度に達すると,空はほとんど完全に暗くなり肉
      眼で6等星まで見え天文観測ができる
      (12度~18度,天文薄明)。
    

    PHPでは、date_sun_info()関数でこの情報が取得できます。

    (1) 市民薄明:civil_twilight_begin と civil_twilight_end
    (2) 航海薄明:nautical_twilight_begin と nautical_twilight_end
    (3) 天文薄明:astronomical_twilight_begin と astronomical_twilight_end

    などが、連想配列で取得できます。

    但し、精度は保証の限りではありません!

    PHP strftime() のwindows サポート

    PHPドキュメント内に、標記関数の全formatパラメータのサポート状況を調査するような事例が記載されています。
    これを、windows7 xampp(PHP 5.6.30) とレンタルサーバ(lolipop php:5.4.45)の双方で実行してみた。

    format lolipop windows
    ‘%’
    ‘A’
    ‘a’
    ‘B’
    ‘b’
    ‘C’ ×
    ‘c’
    ‘D’ ×
    ‘d’
    ‘E’ ×
    ‘e’ ×
    ‘F’ ×
    ‘f’ ×
    ‘G’ ×
    ‘g’ ×
    ‘h’ ×
    ‘H’
    ‘i’ ×
    ‘I’
    ‘J’ ×
    ‘j’
    ‘K’ ×
    ‘k’ ×
    ‘L’ ×
    ‘l’ ×
    ‘M’
    ‘m’
    ‘N’ ×
    ‘n’ ×
    ‘O’ ×
    ‘o’ ×
    ‘P’ ×
    ‘p’
    ‘Q’ ×
    ‘q’ ×
    ‘R’ ×
    ‘r’ ×
    ‘s’ ×
    ‘S’
    ‘T’ ×
    ‘t’ ×
    ‘u’ ×
    ‘U’
    ‘V’ ×
    ‘v’ ×
    ‘W’
    ‘w’
    ‘X’
    ‘x’
    ‘Y’
    ‘y’
    ‘Z’
    ‘z’

    ○:Known format
    ×:Unknown format

    この他、’z’(タイムゾーンオフセット)と’Z’(タイムゾーン略称)の戻り値が
    不正(?)のため、文字化けのような値が表示されるようなものもあります。

    以上から、windowsでは未実装な部分が意外に多いことが分かりました。

    PHP ISO-8601 週番号

    PHPの日付関数をちらちら調べていたところ、標記の問題に直面した。
    問題個所は、strftimeformatパラメータ内”%V”の
    説明文です。この文を引用してみると、
    「ISO-8601:1988 で規定された、指定した年の週番号。週の開始日は月曜日で、第1週は少なくとも4日はあることになる」
    文の前段に問題はないが、後段がどうしても理解できない。
    週の開始日は月曜日」とすると、何故「第1週は少なくとも4日はある」となるのか?
    意地の悪い意見を言わせてもらえば、「第1週に限らず、週は常に7日に決まっている」はずです。

    原文は、次の通り。
    「ISO-8601:1988 week number of the given year, starting with the first week of the year with at least 4 weekdays, with Monday being the start of the week」
    英語は苦手なので、Googleさんに翻訳してもらいました。
    「ISO-8601:特定の年の1988年の週番号。少なくとも週4日の週の最初の週から始まり、月曜日は週の開始日」
    いろいろ怪しい部分もありますが、こちらの方が表現的には正しいのではないか?
    言葉で表現すると難しいので、表にして説明してみる。

    ケース
    1 1日 2日 3日 4日 5日 6日 7日
    2 1日 2日 3日 4日 5日 6日
    3 1日 2日 3日 4日 5日
    4 1日 2日 3日 4日
    5 1日 2日 3日
    6 1日 2日
    7 1日

    「週4日」とは、年初からの日数で、週内に4日以上ある最初の週が、その年の第1週に
    成るということです。つまり、上の表でいうと
    (1)ケース1~ケース4:その年の第1週
    (2)ケース5~ケース7:前年の第53週
    ということになります。

    PHPのドキュメントは、誰もが認める素晴らしいものです。
    批判するつもりでこれを書いたのではなく、コンタクト方法が分からないので
    関係者が偶然これを見て修正して戴ければとの思いで公開するものです。ご了承願います。

    phpでhtml要素の一部を取得する

    phpのDOMを使用してhtml要素(<tag>~</tag>)を取得するのが意外と難しい。
    tagNameやnodeValueの取出し方は、多くの事例があるので探せば直ぐに見つかるのだが
    タグそのものを表示する例はほとんど皆無に近い。

    キーワードをいろいろ変えながら探した結果が次のもの。

    この解決策は、DOMElement クラス内の
    「User Contributed Notes」にある「63」と「15」がヒントになる。
    例を見た方が手っ取り早いので、下に例を示す。

    (1) サンプルとして次の sample.html を使用する

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <title>テストデータ</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <h1>テストデータ</h1>
    <p>&lt;table> の全要素を表示します。</p>
    <table id="test" class="table">
    	<tr class="tr"><th>Header1</th><th>Header2</th></tr>
    	<tr><td class="td">Data1</td><td>Data2</td></td>
    </table>
    <div id="main">
    	<p>test1</p>
    	<p>test2</p>
    	<a href="*">Link1</a>
    	<div id="sub">
    		<p>sub1</p>
    		<p>sub2</p>
    	</div>
    </div>
    </body>
    </html>
    

    (2) table内の全要素を取得する場合

    <?php
    header("Content-Type: text/html; charset=UTF-8");
    // innerHTML形式で要素を出力する例
    // 結果は「ページのソース」で確認のこと
    function DOMinnerHTML(DOMNode $element) { 
        $innerHTML = ""; 
        $children  = $element->childNodes;
    
        foreach ($children as $child) 
        { 
            $innerHTML .= $element->ownerDocument->saveHTML($child);
        }
    
        return $innerHTML; 
    }
    
    $dom= new DOMDocument(); 
    $html = "sample.html";
    @$dom->loadHTMLFile($html);
    // xpathを使用しない場合
    //$domTables = $dom->getElementsByTagName("table"); 
    $xpath = new DOMXpath($dom);
    $domTables = $xpath->query("//table");
    if (!is_null($domTables)) {
    	// Iterate over DOMNodeList (Implements Traversable)
    	foreach ($domTables as $table){ 
    		echo DOMinnerHTML($table); 
    	} 
    }else{
    	echo "一致するデータがありません!";
    }
    ?>
    

    (3)id=”main”であるdiv要素内の全要素を取得する

    <?php
    header("Content-Type: text/html; charset=UTF-8");
    // innerHTML形式で要素を出力する例
    // 結果は「ページのソース」で確認のこと
    function DOMinnerHTML(DOMNode $element) { 
        $innerHTML = ""; 
        $children  = $element->childNodes;
    
        foreach ($children as $child) 
        { 
            $innerHTML .= $element->ownerDocument->saveHTML($child);
        }
    
        return $innerHTML; 
    }
    
    $dom= new DOMDocument(); 
    $html = "sample.html";
    @$dom->loadHTMLFile($html);
    $xpath = new DOMXpath($dom);
    $domTables = $xpath->query("//div[@id='main']");
    if (!is_null($domTables)) {
    	// Iterate over DOMNodeList (Implements Traversable)
    	foreach ($domTables as $table){ 
    		echo DOMinnerHTML($table); 
    	} 
    }else{
    	echo "一致するデータがありません!";
    }
    ?>
    

    (注)結果は、ブラウザの画面を右クリックして、「ページのソースを表示」(Firefoxの場合)で確認してください。

    xamppへのXdebugのインストールと設定

    諸般の都合でXdebugが必要になった。
    インストールしようと、いろいろググってみると
    大半の情報が、\xampp\php\extにxdebug.dllが存在し
    php.iniにもその指定がコメントで記述してあること
    を前提としたもの。
    つい最近、phpを5.6.30にv-upした所為なのだろうか、
    私の環境にはそれが無いし、
    php.iniにもそのような記述がない。

    とは言え、あちこち調べて朧げに分かったことは、
    Xdebugのインストールとは、次の内容の作業ことを
    言うらしいとのこと。
    (1)Xdebugをダウンロードする。
    (2)ダウンロードした dll を\xampp\php\extに配置する。
    (3)php.ini にxdebug 情報を追記する。
    (このことは、GitHubに端的に記述してありました。)

    今回は、こちらから「PHP 5.6 VC11 TS (32 bit) 」をダウンロードしました。
    xampp phpのv-upで、64bit版のインストールができなかったので
    32bit版をダウンロードしています。

    これを(2)にコピーして、php.iniの最下部に次の行を追加します。

    [XDebug]
    zend_extension = "c:\xampp\php\ext\php_xdebug-2.5.0-5.6-vc11.dll"
    xdebug.remote_autostart = 1
    xdebug.profiler_append = 0
    xdebug.profiler_enable = 0
    xdebug.profiler_enable_trigger = 0
    xdebug.profiler_output_dir = "c:\xampp\tmp"
    ;xdebug.profiler_output_name = "cachegrind.out.%t-%s"
    xdebug.remote_enable = 1
    xdebug.remote_handler = "dbgp"
    xdebug.remote_host = "127.0.0.1"
    xdebug.remote_log="c:\xampp\tmp\xdebug.txt"
    xdebug.remote_port = 9000
    xdebug.trace_output_dir = "c:\xampp\tmp"
    ; 3600 (1 hour), 36000 = 10h
    xdebug.remote_cookie_expire_time = 36000
    

    なお、

    zend_extension = "c:\xampp\php\ext\php_xdebug-2.5.0-5.6-vc11.dll"
    

    の部分は、自分の環境やダウンロードしたXdebugに基づいて変更する
    必要があります。

    変更したphp.iniを保存後は、xamppコントロール・パネルから
    Apacheを、stop→start としてphp.iniの変更を反映させます。

    PHP loadHTMLFile に再びハマる

    PHP DOM操作における文字化けで1回既にハマっていたのに、今回また同じ様にハマってしまった。
    しかも、2日がかりで。
    悔しいので、今回気付いた点を纏めておきたい。

    (1)UTF-8Nで書いたソースは何にエンコードされるのか?

    UTF-8(BOMあり)にエンコードされるようです。
    試しに、sample.htmlをUTF-8(BOMあり)で保存して実行すると
    文字化けをせず、正しく表示されます。

    (2)loadHTMLFile()以外の場合は?

    $sou = file_get_contents(./sample.html);
    echo &sou;
    

    として確認してみると、文字化けはしません。
    と言うことは

    $dom = new DOMDocument();  // ①
    @$dom->loadHTML($sou);     // ②
    

    ②の中で、HTMLのmeta情報に基づいてコードが変換される
    と言うことなのでしょう。

    (3)php.iniとの関連は?

    本件に関しては、、全く関連なしでした。
    原因が(2)にあるので、当然と言えば当然です。
    いろいろと、2日間ももがき苦しんだ中で、php.iniのmbstringの設定が
    推奨されなく成っている所が何点かあるのが分かりました。

    対策ついでに、PHP-5.4.7からPHP-5.6.30にバージョンアップも
    行いましたが、php.iniのmbstringの設定を以下の通り変更しています。

    名前 設定値 説明
    mbstring.language Japanese コメントを外しただけです
    mbstring.encoding_translation Off コメントを外しました

    mbstring.http_input,mbstring.http_output,mbstring.internal_encoding
    は、5.6.0以降は非推奨とのことなので、コメントのままにしてあります。

    印刷用語

    用語の羅列のみ
    1.合字(リガチャ:Ligature)
    2.字形(グリフ:Glyph)
    3.約物(Punctuation)句読点等々
    4.圏点、傍点、脇点
    5.書体(Font)
    6.踊り字(約物にほぼ同じ)