HTML Tidyで整形
はじめに
このサイトはxtを使用してxmlからxhtmlに変換して公開している.ブラウザで見る分には支障ないのだが,ソースとしてみた場合,xtの作成するxhtmlは決して見やすいものではない.整形するためのperlスクリプトを作ってみたのだが,なかなかきれいには整形できない.HTML Tidy(以下tidy)はこの悩みを解消してくれそうだ.
インストール
Windowsで動くバイナリもあるが,普段cygwinを使っているのでcygwin版をインストールする.cygwinからsetup.exeをダウンロードして起動する.tidyはカテゴリTextの中にある.デフォルトではインストール対象から外れているので,インストール対象に変更する.後はsetup.exeがうまい具合にやってくれる.
コマンドラインで動かしてみる
トップページのindex.htmlをサンプルにして動かしてみた.index.htmlの文字コードに合わせてオプションに-utf8,インデントをしてほしいので-iをつけた.なお,-hでヘルプを見ることができる.
$ tidy -utf8 -i index.html
Info: Document content looks like HTML 3.2
No warnings or errors were found.
index.htmlはxhtml1.1なのだが,html3.2になってしまっている.xml(xhtml)に見てくれるように-xmlを指定した.
$ tidy -xml -utf8 -i index.html
No warnings or errors were found.
エラーにはなっていない.しかし,標準出力に出てくるはずの処理結果が出てこない.もっと簡単な別ファイルを作って試してみた.
$ cat sam.html
<html>
<head>
<title>sample</title>
</head>
<body>
this is sample
</body>
</html>
$ tidy -xml -i sam.html
No warnings or errors were found.
<html>
<head>
<title>sample</title>
</head>
<body>this is sample</body>
</html>
うまく動いている.
文字コードなのだろうか?試しに,imdkcvを使って文字コードをシフトJISにしてみた.
$ imdkcv -sn index.html|tidy -shiftjis -xml -i
Info: Doctype given is "-//W3C//DTD XHTML 1.1//EN"
No warnings or errors were found.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type"
content="text/javascript" />
<meta name="Generator"
content="written by xyzzy. transformed by XT" />
<meta name="wwwc" content="2003.7.13 歳時記・リンク更新" />
<link rel="stylesheet" type="text/css"
href="css/tabs_in_top.css" />
<link rel="stylesheet" type="text/css" href="css/top.css" />
<link rel="start" href="index.html" />
---以下省略---
うまくいった.
utf8とutf8nの違いなのだろうか.xmlファイルはutf8nで書いている.utf8だとxtがうまく動かなかったからだ.xtはutf8nならうまく動いた.xtが対応しているutf8はutf8ではなくutf8nのようだ.
tidyはutf8nではうまく動かない.tidyが対応しているutf8はutf8nではなくutf8のようだ.utf8nではうまく動かない.ややこしい.とりあえず,シフトJISに変換すると何とかなるので,良しとしよう.ビバ,シフトJIS.
preタグと改行
これで終わりかと思ったが,<pre>タグで囲った内容が一行おきに出てきてしまうことに気がついた.
$ imdkcv -sn _tidy.html|tidy -shiftjis -xml -i
No warnings or errors were found.
<?xml version="1.0"?>
<html>
<head>
<title>sample</title>
</head>
<body>this is sample
<pre>
this is pre line1.
this is pre line2.
</pre></body>
</html>
imdkcvにオプション-aを指定して,改行コードを0x0a(lf)だけにしたら解決した.
$ imdkcv -sn -a _tidy.html|tidy -shiftjis -xml -i
No warnings or errors were found.
<?xml version="1.0"?>
<html>
<head>
<title>sample</title>
</head>
<body>this is sample
<pre>
this is pre line1.
this is pre line2.
</pre></body>
</html>
できあがったファイルの改行コードは0x0aのはずなのだが,エディタ(xyzzy)で見ると,crlfになっている.よく分からない.実害がないのでとりあえず放置.
ant用タスクの修正
xmlからxhtmlへの変換はantを使って行っている.antで使うxmlファイルの該当部分にimdkcvとtidyを使った整形を追加する.パイプの使い方が分からないので,データの受渡しには一時ファイルを使っている.
<target name="format"> <tempfile property="sjis"/> <tempfile property="utf8"/> <!-- シフトJISに変換 --> <exec executable="imdkcv" output="${sjis}"> <arg line="-sn -a '${html}'"/> </exec> <!-- 整形 --> <exec executable="tidy"> <arg line="-xml -shiftjis -wrap 500 -im '${sjis}'"/> </exec> <!-- utf8nに変換 --> <exec executable="imdkcv" output="${utf8}"> <arg line="-u8 '${sjis}'"/> </exec> <!-- 微調整 --> <exec executable="perl" output="${html}"> <arg line="'${xsl.path}/format.pl' '${utf8}'"/> </exec> <delete file="${sjis}"/> <delete file="${utf8}"/> </target>
xmlをxhtmlに変換するためのxmlファイルは,共通で使うbase.xmlと個別に用意したbuid.xmlを作成している.あんまり格好の良い物ではないが,付録として全リストをつけた.
おわりに
今回はtidyを整形にしか使っていない.これ以外にも様々な機能があるのだが,それについては,以下に挙げた参考サイトを参照してほしい.そちらのほうがずっと詳しい.参考サイト
- HTML Tidy Project Page
- 本家.Windowsで動くバイナリもあり.
- プログラマー天国
- プログラマーのためのHTML Tidy入門を読めば,一通り使えるようになれる.
- cygwin
- Windowsで動くunix環境.
- いまでぃのホームページ
- 文字コード変換プログラムimdkcvがダウンロードできる.今回も大活躍.
付録
<!-- base.xml -->
<project name="xml2html" default="xslt" basedir=".">
<property environment="env"/>
<property name="xt.path" value="${env.PROGRAMFILES}/xt"/>
<property name="xsl.path" value="${user.home}/My Documents/web/xsl"/>
<property name="htmllint" value="${env.PROGRAMFILES}/htmllint/htmllint"/>
<target name="up-to-date">
<uptodate property="isIndexUpToDate" targetfile="${html}">
<srcfiles dir="." includes="${xml}"/>
<srcfiles dir="${xsl.path}" includes="${xslt} framework.xsl"/>
</uptodate>
</target>
<target name="xslt" depends="up-to-date" unless="isIndexUpToDate">
<java classname="com.jclark.xsl.sax.Driver" failonerror="true">
<classpath>
<pathelement path="${xt.path}/xt.jar;${xt.path}/lib/xp.jar;${xsl.path};."/>
<pathelement path="${java.class.path}"/>
</classpath>
<arg line="${xml} '${xsl.path}/${xslt}' ${html}"/>
</java>
<antcall target="format"/>
<antcall target="htmllint"/>
</target>
<target name="format">
<tempfile property="sjis"/>
<tempfile property="utf8"/>
<exec executable="imdkcv" output="${sjis}">
<arg line="-sn -a '${html}'"/>
</exec>
<exec executable="tidy" failonerror="true">
<arg line="-xml -shiftjis -wrap 500 -im '${sjis}'"/>
</exec>
<exec executable="imdkcv" output="${utf8}">
<arg line="-u8 '${sjis}'"/>
</exec>
<exec executable="perl" output="${html}">
<arg line="'${xsl.path}/format.pl' ${utf8}"/>
</exec>
<delete file="${sjis}"/>
<delete file="${utf8}"/>
</target>
<target name="htmllint">
<tempfile property="lint.result"/>
<exec executable="perl" output="${lint.result}">
<arg line="'${htmllint}' ${html}"/>
</exec>
<exec executable="imdkcv">
<arg line="-sn '${lint.result}'"/>
</exec>
<delete file="${lint.result}"/>
</target>
<target name="clean">
<delete>
<fileset dir="." includes="*.html"/>
</delete>
</target>
</project>
<!-- build.xml -->
<project name="xml2html" default="index" basedir=".">
<property name="root" value="."/>
<target name="index">
<ant antfile="${root}/base.xml">
<property name="xslt" value="top.xsl"/>
<property name="xml" value="index.xml"/>
<property name="html" value="index.html"/>
</ant>
</target>
<target name="all" depends="index"/>
<target name="clean">
<ant antfile="${root}/base.xml" target="clean"/>
</target>
</project>