私とHTML

最新15件を表示します。このリソース群の時系列順リストタイトルリスト、またこのリソースのAtom表現RSS1.0表現も参照できます。

PagingNavigatorが出すHTMLがアレなので直した

たとえば「全部で100件ある記事を15件ずつ表示したい」というのをWicketでやるにはPageableListViewPagingNavigatorを使う。PagingNavigatorはページャを自動に生成してくれる便利なクラスだが、生成されるHTMLが大変微妙で、たとえば「最初」へのリンクのテキストが"<<"、「次」へのリンクは">"となっている。もちろん「次」へのリンクにrel="next"などついているわけもなく、明らかにユーザビリティが低い。実際にWicketのソースからPagingNavigator.htmlを見ると以下のようになっていた:

<wicket:panel>
    <a wicket:id="first">&lt;&lt;</a>&nbsp;<a wicket:id="prev">&lt;</a>
    <span wicket:id="navigation">
        <a wicket:id="pageLink" href="#"><span wicket:id="pageNumber">5</span></a>
    </span>
    <a wicket:id="next">&gt;</a>&nbsp;<a wicket:id="last">&gt;&gt;</a>
</wicket:panel>

そこで、PagingNavigatorを継承したクラスであるMyPagingNavigatorを作成する。

javaファイルのほうはPagingNavigatorをextendsした上で、PagingNavigator.javaを丸コピしておく。htmlファイルは:

<wicket:panel>
<ol class="pager">
    <li><a rel="first" href="" wicket:id="first">最初</a></li>
    <li><a rel="prev" href="" wicket:id="prev">前</a></li>
    <li wicket:id="navigation"><a wicket:id="pageLink" href="#"><span wicket:id="pageNumber">5</span></a></li>
    <li><a rel="next" href="" wicket:id="next">次</a></li>
    <li><a rel="last" href="" wicket:id="last">最後</a></li>
</ol>
</wicket:panel>

こんな感じ。ただ、実際に表示させてみたところちょっと気になるところがあった。

<ol class="pager">
    <li><span rel="first"><em>最初</em></span></li>
    <li><span rel="prev"><em>前</em></span></li>
    <li><span><em><span>1</span></em></span></li><li><a href="hogehoge"><span>2</span></a></li>
    <li><a href="hogehoge" rel="next">次</a></li>
    <li><a href="hogehoge" rel="last">最後</a></li>
</ol>

リンクがないときにa要素がspan要素とem要素に置き換わり、さらにspan要素にrel属性が残ってしまう。これでは気持ち悪いので、この変換がどこで行われるのか追いかけてみたけど分からなかった。時間があったらもっと詳しく見ていきたい。

タグ
HTML

Mozilla Java Html Parserが動いた

5ヶ月前から放置していたMozilla Java Html Parserだが、さっき入れなおしてみたら動いた。前回はMozillaHtmlParser.jarの中に入っていたcom.dappit.Dapper.parser.example.ParserExampleを参考にしたが、今回はQuick Startを参考にした、というかinitメソッドに渡す値が変だったのでそれを直せばよかったみたい。Quick Startに書いてあるとおりに、C:\Program Files\MozillaHtmlParser\mozilla.dist.bin.winとかを環境変数のPATHに加えたのだが、ソースにもその文字列をまた書くことになってしまった。多分もっと頭の良い方法があるのでそのうち調べる。

ソースは以下のとおり:

import java.io.File;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.dappit.Dapper.parser.EnviromentController;
import com.dappit.Dapper.parser.MozillaParser;

public class MJHP {
    public static void main(String[] args) throws Exception {
        File parserLibraryFile = new File("C:\\Program Files\\MozillaHtmlParser\\native\\bin\\MozillaParser" + EnviromentController.getSharedLibraryExtension()); 
        String parseLibrary = parserLibraryFile.getAbsolutePath(); 
        MozillaParser.init(parseLibrary, "C:\\Program Files\\MozillaHtmlParser\\mozilla.dist.bin.win"); 
        MozillaParser parser = new MozillaParser();
        Document document = parser.parse("<html>Hello world!</html>");
        System.out.println(dom2string((Node)document.getDocumentElement()));
    }
    public static String dom2string(Node n) {
        StringBuilder buf = new StringBuilder();
        switch(n.getNodeType()) {
        case Node.TEXT_NODE :
            return n.getNodeValue();
        case Node.ELEMENT_NODE :
            buf.append(String.format("<%s", n.getNodeName()));
            NamedNodeMap attrs = n.getAttributes();
            for(int i = 0; i < attrs.getLength(); i++) {
                Node attr = attrs.item(i);
                buf.append(String.format(" %s=\"%s\"", attr.getNodeName(), attr.getNodeValue()));
            }
            buf.append(">");
            for(Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
                buf.append(dom2string(child));
            }
            buf.append(String.format("</%s>", n.getNodeName()));
        }
        return buf.toString();
    }
}

実行させると、以下のような出力を得られる:

Operating system : Windows XP
<html><body>Hello world!</body></html>
Initializing XPCOM from location : C:\Program Files\MozillaHtmlParser\mozilla.dist.bin.win...

ひどいHTML特集Mozilla Java Html Parser編を加えた。table直下にtbodyを補完するHTMLパーサは今のところこれだけ。その一方tr直下にtrが来てしまうなどの問題も見られた。

タグ
HTML

ホムペ作ったー\(^o^)/

勉強会メンバーの一人がハムスター島でホムペを運営しているとのことで私の中で空前のホムペブームが到来、そのままアカウントを取って自分のホムペを立ち上げた。

動作確認かっこわらいをOpera9.27で取りつつ作成したため、Firefox2やIE6で見ると残念な結果になってしまった。FirefoxやIEで見るのは同一保持権の侵害かっこわらいなのでOperaユーザ率を高める意味も込めて皆さんOperaをぜひインストールしてアクセスしていきましょう!でも実際そんなの面倒だと思うので、下にキャプチャを置いておきますね><

IE6
Firefox2
Opera9
Safari3

きょうびはブログ全盛の世の中でみなさんなかなかホムペを持つこともないかもしれませんが、一つ作っておくと名刺代わりにもなっていいよ!オヌヌメ!

などのネタはともかく、気づいたところ:

iframeとかobjectとかはどうなるのかな? まあどうでもいいや。あと、最近はニコニコ動画とかもあるし、はてブのコメントをニコニコ動画風に見るサービスだってあるのだからmarqueeの復権があってもおかしくないのではないか。知らなかったんだけどmarqueeには以下のような愉快な属性が定義されているらしいぞ! みんなでぜひ文字列を上下左右に動かそう!

marquee要素の主な属性
属性名属性値意味
behaviorscroll(初期値。一方向スクロール), slide(端にぶつかると停止), alternate(往復スクロール)スクロールの仕方を指定。
directionleft(初期値。右から左), right(左から右), down(上から下), up(下から上)スクロールの方向を指定。
scrollamount数値スクロールする量をピクセル単位で指定。
scrolldelay数値スクロール間隔をミリ秒単位で指定。

ということで、熱に30分ほど浮かされて正気に戻りました。

タグ
HTML

Mozilla Java Html Parserを使ってみた

マイコミジャーナルで紹介されていたのでMozilla Java Html Parserを触ってみたがうまくいかなかった。

SourceforgeからダウンロードしてMozillaHtmlParser.jarおよびlibフォルダに含まれていたJARファイル群をEclipseの「外部アーカイブ」に追加。以下のような簡単なソースを書いた (ていうかMozillaHtmlParser.jarの中に入っていたcom.dappit.Dapper.parser.example.ParserExampleをさらに簡単にしたもの):

import java.io.File;

import org.w3c.dom.Document;

import com.dappit.Dapper.parser.EnviromentController;
import com.dappit.Dapper.parser.MozillaParser;

public class Test {
    public static void main(String[] args) throws Exception {
        File parserLibraryFile = new File("./native/bin/MozillaParser" + EnviromentController.getSharedLibraryExtension());
        String parserLibrary = parserLibraryFile.getAbsolutePath();
        System.out.println("Loading Parser Library :" + parserLibrary);
        final File mozillaDistBinDirectory = new File("mozilla.dist.bin."+EnviromentController.getOperatingSystemName());
        MozillaParser.init(parserLibrary,mozillaDistBinDirectory.getAbsolutePath());        
        
        try {
            MozillaParser parser = new MozillaParser();
            System.out.println("parsing...");
            
            String html = "<html>Test</html>";
            Document document = parser.parse(html);
            System.out.println("Generated document :" + ((org.dom4j.Document)document).asXML());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("done...");
    }
}

実行させると:

Operating system : Windows XP
Loading Parser Library :C:\Program Files\MozillaJavaHTMLParser\native\bin\MozillaParser.dll
parsing...
Cannot convert: null into a W3C DOM Node
done...
Initializing XPCOM from location : C:\Program Files\MozillaJavaHTMLParser\mozilla.dist.bin.win...
org.w3c.dom.DOMException: Not supported yet
    at org.dom4j.dom.DOMNodeHelper.notSupported(DOMNodeHelper.java:468)
    at org.dom4j.dom.DOMNodeHelper.asDOMNode(DOMNodeHelper.java:405)
    at org.dom4j.dom.DOMNodeHelper.getParentNode(DOMNodeHelper.java:79)
    at org.dom4j.dom.DOMElement.getParentNode(DOMElement.java:100)
    at com.dappit.Dapper.parser.DomDocumentBuilder.buildDocument(DomDocumentBuilder.java:109)
    at com.dappit.Dapper.parser.MozillaParser.parse(MozillaParser.java:84)
    at Test.main(Test.java:21)

DomDocumentBuilder.javaの109行目付近を見ると:

            case ParserInstruction.CloseNode:
            {
                if (currentElement == null)
                {
                    System.err.println("Error : Close Node where no OpenNode was called. trying to fix...");
                    // this.dump();
                }
                else if (closeHtml)
                    currentElement = (Element) currentElement.getParentNode();

変数currentElementはorg.w3c.Elementインターフェイスのインスタンスで、HTML要素の親ノードを取得しようとしたか、またはルートノードの親ノードを取得しようとしてNULLが出たのかなーと思ったが、まさかそんな基本的なところで躓くようなスクリプトが一般に公開されているとも思えないので私のやり方が悪いはず。でも見当がつかない。

Mozilla HTML Parserについて言及しているサイトを調べたが、bits and bytesの紹介記事 (直接Cから叩いている) とプログラム技術板の質問スレ (回答なし) くらいしか見当たらなかった。後者については、たしかにQuick Startには

Document domDocument = MozillaParser.getInstance().parse("<html>Hello world!</html>");
MozillaParser.getInstance().stopRunning();

なんて書いてあるからそうコーディングしてしまうけど、ちゃんとExampleファイルを見てみるとフツーにMozillaParserをnewしていたという^^ でもここを乗り越えると今私が嵌まっている罠が待っているわけで。誰かえらい人の降臨を待ちたいところ。

ちゃんとやったら動いた

タグ
HTML

IEではてなスターが表示されなかった

はてなスターを設けたとあるHTML文書について、FirefoxやOperaでははてスタのアイコンが現れるのにIEだと現れないという問題が発生した。あれこれ試行錯誤してみたところ、どうやら<textarea name="comment"><dl id="comment">が原因のようだった。IEはName属性とID属性を同じ名前空間で管理しているのかな。多分それが理由で、getElementById("comment")を実行すると先に現れるTextarea要素にマッチしてしまっていた模様。

と思ったけど、もしかしたら、Name属性値とID属性値を同じ空間で管理するのはまっとうな挙動で、OperaやFirefoxは同じIDがあったら後に出てくる要素を優先しているだけなのかもしれない。これについては詳しく調査する必要があるような気もする、というかID属性の値とかもっと考えてコーディングしていれば今回のような問題は発生しない。

タグ
HTML

ひどいHTMLをSAXパーサに読ませる

先日取り上げたexblogのひどいHTMLを、HTML向けSAXパーサに読ませるとどうなるかの実験。startElement()やendElement()がどうコールされるかによって、パーサごとの性格が現れる。

コールバックメソッド

levelはネストの深さを表すインスタンス変数。

public void startElement(String uri, String localName, String qName, Attributes attrs){
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.print("<"+localName);
    for(int i = 0; i < attrs.getLength(); i++)
        System.out.print(" "+attrs.getQName(i)+"=\""+attrs.getValue(i)+"\"");
    System.out.println(">");
    level++;
}
public void endElement(String uri, String localName, String qName){
    level--;
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.println("</"+localName+">");
}
public void characters(char[] ch, int offset, int length){
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.println(StringUtils.substring(new String(ch,offset,length).trim(),0,20));
}

対象となるHTML (1)

例によって見やすいように改行とインデントを加えています。

<DIV CLASS=MNBODY>
 <TABLE WIDTH=150 BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>
  <TR>
   <TD COLSPAN=3>
    <FORM NAME=finder METHOD=GET ACTION=http://www.exblog.jp/search/>
     <INPUT TYPE=HIDDEN NAME=blogid VALUE=970055211>
   </TD>
  </TR>
  <INPUT TYPE=HIDDEN NAME=t VALUE=0>
  <TR>
   <TD WIDTH=105 ALIGN=LEFT>
    <INPUT TYPE=TEXT NAME=q SIZE=15  CLASS=TXTFLD>
   </TD>
   <TD WIDTH=5></TD>
   <TD WIDTH=40 ALIGN=LEFT>
    <INPUT TYPE=SUBMIT VALUE="検索" STYLE="WIDTH:40;HEIGHT:20;">
   </TD>
  </TR>
  <TR>
   <TD COLSPAN=3>
    </FORM>
   </TD>
  </TR>
 </TABLE>
</DIV>

CyberNeko HTML Parserの場合

<DIV class="MNBODY">
 <TABLE width="150" border="0" cellspacing="0" cellpadding="0" align="CENTER">
  <TR>
   <TD colspan="3">
    <FORM name="finder" method="GET" action="http://www.exblog.jp/search/">
     <INPUT type="HIDDEN" name="blogid" value="970055211">
     </INPUT>
    </FORM>
   </TD>
  </TR>
  <INPUT type="HIDDEN" name="t" value="0">
  </INPUT>
  <TR>
   <TD width="105" align="LEFT">
    <INPUT type="TEXT" name="q" size="15" class="TXTFLD">
    </INPUT>
   </TD>
   
   <TD width="5">
   </TD>
   
   <TD width="40" align="LEFT">
    <INPUT type="SUBMIT" value="検索" style="WIDTH:40;HEIGHT:20;">
    </INPUT>
   </TD>
  </TR>
  <TR>
   <TD colspan="3">
   </TD>
  </TR>
 </TABLE>
</DIV>

td要素の終了を優先し、td要素内のform要素に終了タグを補完した。table直下にinputが残っている。

Cobra 0.98.2でも同様の結果になった。

TagSoupの場合

Tag Soupの場合、URIを指定して直接読ませたりInputStreamを読ませたりすると日本語が文字化けするので、いったんStringに落としたものをSAXParserに読ませた。

<div class="MNBODY">
 <table align="CENTER" width="150" border="0" cellspacing="0" cellpadding="0">
  <tr>
   <td colspan="3" rowspan="1">
    <form enctype="application/x-www-form-urlencoded" method="GET" name="finder" action="http://www.exblog.jp/search/">
     <input type="HIDDEN" name="blogid" value="970055211">
     </input>
     <input type="HIDDEN" name="t" value="0">
     </input>
     <tr>
      <td align="LEFT" colspan="1" rowspan="1" width="105">
       <input type="TEXT" class="TXTFLD" name="q" size="15">
       </input>
      </td>
      <td colspan="1" rowspan="1" width="5">
      </td>
      <td align="LEFT" colspan="1" rowspan="1" width="40">
       <input type="SUBMIT" value="検索" style="WIDTH:40;HEIGHT:20;">
       </input>
      </td>
     </tr>
     <tr>
      <td colspan="3" rowspan="1">
      </td>
     </tr>
    </form>
   </td>
  </tr>
 </table>
</div>

form要素の連続性を優先したが、結果としてform要素の直下にtr要素が出現してしまった。

HTMLEditorKit.ParserCallbackの場合

これはHTML3.2のパーサで、XHTMLを読ませると具合が悪い。でもついでなのでやってみた。ソースは:

public void handleStartTag(HTML.Tag tag, MutableAttributeSet attrs, int pos){
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.print("<"+tag);
    Enumeration e = attrs.getAttributeNames();
    while(e.hasMoreElements()){
        Object o = e.nextElement();
        System.out.print(" "+o+"=\""+attrs.getAttribute(o)+"\"");
    }
    System.out.println(">");
    level++;
}
public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attrs, int pos){
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.print("<"+tag);
    Enumeration e = attrs.getAttributeNames();
    while(e.hasMoreElements()){
        Object o = e.nextElement();
        System.out.print(" "+o+"=\""+attrs.getAttribute(o)+"\"");
    }
    System.out.println(" />");
}
public void handleEndTag(HTML.Tag tag, int pos){
    level--;
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.println("</"+tag+">");
}
public void handleText(char[] data, int pos){
    for(int i = 0; i < level; i++) System.out.print(" ");
    System.out.println(StringUtils.substring(new String(data).trim(),0,20));
}

結果は

<div class="mnbody">
 <table cellspacing="0" align="center" border="0" width="150" cellpadding="0">
  <tr>
   <td colspan="3">
    <form name="finder" action="http://www.exblog.jp/search/" method="get">
     <input value="970055211" name="blogid" type="hidden" />
    </form>
   </td>
  </tr>
  <tr _implied_="true">
   <td _implied_="true">
    <input value="0" name="t" type="hidden" />
   </td>
  </tr>
  <tr>
   <td align="left" width="105">
    <input name="q" size="15" type="text" class="txtfld" />
   </td>
   <td width="5">
   </td>
   <td align="left" width="40">
    <input style="WIDTH:40;HEIGHT:20;" value="検索" type="submit" />
   </td>
  </tr>
  <tr>
   <td colspan="3">
   </td>
  </tr>
 </table>
</div>

table直下のinput要素をtrとtdでラップした。3つの中では結構成功に近い結果を出したのではないだろうか。ただ、このパーサはXHTMLにまったく対応していないのが残念。バージョンアップしないのかな。

Mozilla Java Html Parserの場合

これはSAXパーサではないので、DOMをプリントする必要があるが、その結果以下のようになった:

<div class="MNBODY">
 <table width="150" border="0" cellspacing="0" cellpadding="0" align="CENTER">
  <tbody>
   <tr>
    <td colspan="3">
     <form name="finder" method="GET" action="http://www.exblog.jp/search/">
      <input type="HIDDEN" name="blogid" value="970055211"></input>
     </form>
    </td>
    <input type="HIDDEN" name="t" value="0"></input>
    <tr>
     <td width="105" align="LEFT">
      <input type="TEXT" name="q" size="15" class="TXTFLD"></input>
     </td>
     <td width="5"></td>
     <td width="40" align="LEFT">
      <input type="SUBMIT" value="検索" style="WIDTH:40;HEIGHT:20;"></input>
     </td>
    </tr>
    <tr>
     <td colspan="3">
     </td>
    </tr>
   </tr>
  </tbody>
 </table>
</div>

tbodyが補完されているのがいかにもMozillaのパーサという感じだが、tr直下にinputやtrが来てしまっている点が惜しい。とはいえ、これ以上どう修正すればいいのだろう。

HTMLCleanerの場合

<div class="MNBODY">
 <input name="t" type="HIDDEN" value="0"></input>
 <table align="CENTER" border="0" cellpadding="0" cellspacing="0" width="150">
  <tbody>
   <tr>
    <td colspan="3">
     <form action="http://www.exblog.jp/search/" method="GET" name="finder">
      <input name="blogid" type="HIDDEN" value="970055211"></input>
     </form>
    </td>
   </tr>
   <tr>
    <td align="LEFT" width="105">
     <input class="TXTFLD" name="q" size="15" type="TEXT"></input>
    </td>
    <td width="5"></td>
    <td align="LEFT" width="40">
     <input style="WIDTH:40;HEIGHT:20;" type="SUBMIT" value="検索"></input>
    </td>
   </tr>
   <tr>
    <td colspan="3"></td>
   </tr>
  </tbody>
 </table>
</div>

実はMozillaParserより頭が良かったりして。

対象となるHTML (2)

もう1つ例を挙げる。p要素下にdiv要素があり、さらにその子供にp要素があるケース。具体的に言うと自民大敗、本当の理由 (ニュースを斬る):NBonline(日経ビジネス オンライン)。("(中略)"以外のコメントは元からあったもの)

<td valign="top" rowspan="2" class="main_part">
 <div id="articlecontent">
  <h1 class="articleheader">自民大敗、本当の理由</h1>
  <h2 class="articleheader">小泉改革路線に逆行する安倍自民を国民が拒絶</h2>
  <ul class="articledata">
   <li>2007年8月7日 火曜日</li>
   <li><a href="/bns/author.jsp?ID=131744&OFFSET=0">谷川 博</a></li>
  </ul>
  <div class="articlekeyword_wrapper">
   <div class="articlekeyword">
    <a href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%CF%C0%C5%C0">論点</a> 
    <a href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BB%B2%B1%A1%C1%AA">参院選</a> 
    <a href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%B0%C2%C7%DC%C0%AF%B8%A2">安倍政権</a> 
    <a href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BE%AE%C0%F4%B2%FE%B3%D7">小泉改革</a> 
   </div>
  </div>
  <p>
   <!--囲み -->
   <div class="kakomi">
    <p>参院選での自民党大敗については、既に年金問題、政治とカネ、閣僚の失言などいくつもの原因が挙げられている。だが、河野太郎・衆議院議員は根底にある本質的な敗因は、小泉改革の継承者であるはずの安倍政権と自民党が継承者としての責務を果たさず、むしろ逆行していることだと断ずる。「昔の自民党」に戻るなら、次の選挙も危うい。(聞き手は、日経ビジネス オンライン=谷川 博)</p>
   </div>
   <!--//囲み//  -->
  </p>
  <p>
   <!--画像 -->
   <div class="figure" style="width:250px;">
    <img src="250px1.jpg">
    <p>河野太郎・衆議院議員</p>
   </div>
   <!--//画像// -->
  </p>
  <p><strong>NBO</strong> 参院選は自民党の「歴史的大敗」となりました。年金の記録漏れ問題や「政治とカネ」の問題、閣僚の失言など様々な問題が重なり、自民党に激しい逆風が吹いた結果だと言われています。</p>
  <!--(中略)-->
  <div class="blocktitle_l">
   <iframe width="528" height="100" marginwidth="0" marginheight="0" hspace="0" vspace="0" frameborder="0" scrolling="no" bordercolor="#000000" src="http://bizad.nikkeibp.co.jp/NBP_AD/nbonline/ad/nbo_thisweek.shtml">
   </iframe>
  </div>
 </div>
</td>

インタビュー本文のある段落をCSSセレクタ風に書くと、td.main_part > div#articlecontent > pとなる。

CyberNeko HTML Parserの場合

長くなるので、一部改行とインデントを削除した。

<TD valign="top" rowspan="2" class="main_part">
 <DIV id="articlecontent">
  <H1 class="articleheader">自民大敗、本当の理由</H1>
  <H2 class="articleheader">
   小泉改革路線に逆行する安倍自民を国民が拒
  </H2>
  <UL class="articledata">
   <LI>2007年8月7日 火曜日</LI>
   <LI><A href="/bns/author.jsp?ID=131744&OFFSET=0">谷川 博</A></LI>
  </UL>
  <DIV class="articlekeyword_wrapper">
   <DIV class="articlekeyword">
    <A href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%CF%C0%C5%C0">論点</A> 
    <A href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BB%B2%B1%A1%C1%AA">参院選</A> 
    <A href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%B0%C2%C7%DC%C0%AF%B8%A2">安倍政権</A> 
    <A href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BE%AE%C0%F4%B2%FE%B3%D7">小泉改革</A> 
   </DIV>
  </DIV>
  <P>
   <DIV class="kakomi">
   </DIV>
  </P>
  <P>
   参院選での自民党大敗については、既に年金
   の選挙も危うい。(聞き手は、日経ビジネス
  </P>
 </DIV>
 <P>
 </P>
 <P>
  <DIV class="figure" style="width:250px;">
   <IMG src="250px1.jpg">
   </IMG>
  </DIV>
 </P>
 <P>河野太郎・衆議院議員</P>
 <P>
 </P>
 <P>
  <STRONG>NBO</STRONG> 参院選は自民党の「歴史的大敗」となりま
 </P>
 <!--中略-->
 <DIV class="blocktitle_l">
  <IFRAME width="528" height="100" marginwidth="0" marginheight="0" hspace="0" vspace="0" frameborder="0" scrolling="no" bordercolor="#000000" src="http://bizad.nikkeibp.co.jp/NBP_AD/nbonline/ad/nbo_thisweek.shtml">
  </IFRAME>
 </DIV>
</TD>

参院選での自民党大敗~の段落がdiv.kakomiから外に出てしまっている。そのあおりで、インタビュー本文のある段落の場所もtd.main_part > pとなってしまった。なので、NekoHTMLのDOMパーサでdiv.kakomidiv#articlecontentを取得しようと思ってもうまくいかない。前者は空白のみで、後者は自民大敗、本当の理由から(聞き手は、日経ビジネス オンライン=谷川 博)までしか取得できない。

TagSoupの場合

上と同じように、一部改行と空白を削除したところがある。

<td colspan="1" rowspan="2" valign="top" class="main_part">
 <div id="articlecontent">
  <h1 class="articleheader">自民大敗、本当の理由</h1>
  <h2 class="articleheader">
    小泉改革路線に逆行する安倍自民を国民が拒</h2>
  <ul class="articledata">
   <li>2007年8月7日 火曜日</li>
   <li>
    <a shape="rect" href="/bns/author.jsp?ID=131744&OFFSET=0">谷川 博</a>
   </li>
  </ul>
  <div class="articlekeyword_wrapper">
   <div class="articlekeyword">
    <a shape="rect" href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%CF%C0%C5%C0">論点</a> 
    <a shape="rect" href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BB%B2%B1%A1%C1%AA">参院選</a> 
    <a shape="rect" href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%B0%C2%C7%DC%C0%AF%B8%A2">安倍政権</a> 
    <a shape="rect" href="/bns/bnsearch.jsp?BID=1006&OFFSET=0&SEARCH_TEXT=%BE%AE%C0%F4%B2%FE%B3%D7">小泉改革</a> 
   </div>
  </div>
  <p></p>
  <div class="kakomi">
   <p>
    参院選での自民党大敗については、既に年金
   </p>
  </div>
  <p></p>
  <div class="figure" style="width:250px;">
   <img src="250px1.jpg"></img>
   <p>河野太郎・衆議院議員</p>
  </div>
  <p>
   <strong>NBO</strong> 参院選は自民党の「歴史的大敗」となりま
  </p>
  <!--中略-->
  <div class="blocktitle_l">
   <iframe frameborder="0" scrolling="no" width="528" height="100" marginwidth="0" marginheight="0" hspace="0" vspace="0" bordercolor="#000000" src="http://bizad.nikkeibp.co.jp/NBP_AD/nbonline/ad/nbo_thisweek.shtml">
   </iframe>
  </div>
 </div>
</td>

こちらは、p要素下にdiv要素が来ることを防いだ。div#articlecontentがちゃんと直親td要素の終了直前まで続いているので、//div[@id='articlecontent']というXPATH式で本文部分全体を取得できる。

HTMLEditorKit.ParserCallbackの場合

このパーサは想定外の要素に弱いみたいで、処理中にArrayIndexOutOfBoundsExceptionが発生した。原因は84行目をはじめ随所に現れるcomment要素で、これらを削除したところ例外を出さずに処理を終えることができ、TagSoupと似た結果になった。

これら結果を見る限り、HTMLの文法を最も理解しているのはHTMLEditorKit.ParserCallbackのように思える。しかし、このパーサはSAX標準のインタフェースに則っておらず、イリーガルな要素が現れると例外が出てしまうというのが痛い。HTML4.01/XHTML1.0に準じるようなバージョンアップをしてくれないかなー。TagSoupは評判どおり中々優秀だが、InputStreamの日本語を正しく理解してくれないのが難点。日本語の問題を解決したカスタム版があるっぽい? でもこれは実体参照されてしまう問題を解決するためのものだから違うか。1回Stringにすれば問題ないので使えないわけではない。

ShaniXmlParserの場合

ShaniXMLParserは、HTMLのエラー訂正をDOM層でやっているぽい (DocumentBuilderFactoryでDTDを読むかどうかの指定ができるが、SAXParserFactoryにはない) のでちょっと特殊 (<img ~ >となっているとendElement()がコールされない。<img ~ />だとコールされる) だ。

Mozilla Java Html Parserの場合

空のp要素ノードが2つ多く生成されたことを除けば、TagSoupの出力結果と同じになった。

にしてもブラウザ付属のDOMパーサは凄いなあと思う。MozillaのDOMパーサってどうなっているんだろう。

タグ
HTML

HTML勉強会で何を教えるべき?

ということで今週は勉強会週間ということで、前々からネタとして上がっていた「HTMLと私」(元ネタは水野先生のシラバスにあった「OSと私」というフレーズ) を話すことになった。さすがにそれはきついので、とりあえず普通のHTML勉強会を開いた。

さて、HTML勉強会では何から教えるべきなのだろうか。すみけんさんの本みたいに「ももたろう」のマークアップをしながら必要な要素について解説していくのがよいだろうか。それともHTMLの要素群を<html>から順番に解説していくのがよいだろうか。そもそも教えるべきはHTML3.2なのかHTML4.01なのかXHTML1.0なのかXHTML1.1なのか、はたまたISO-HTMLなのか。HTML4.01やXHTML1.0だとしたらTransitionalな要素や属性に触れるべきか――

みんなに何が知りたいか訊いて、あと後輩が書いたHTMLを見て思ったこともあったので、とりあえず文法から話すことにした。件のHTMLはliがbody直下に出ていたり、h3がdl直下にあったりして、とりあえずここら辺を重点的に話した方が良いだろうと思った。HTMLの基本的なところはみんな1年生の講義で習っているはずだしね。この世にはブロック要素とインライン要素がありましてね、という話をしたら、まずブロック要素とかインライン要素とは何だということになった。XTHML1.0 StrictのDTDファイルをプロジェクタに大写ししながら説明を始めた。文字ばかりのDTDファイルが出てきた時点でdnbkか? サーセン

テキトーに解説すると、ブロック要素は段落。矩形。インライン要素はその一部。下線。で、ブロック要素には、(1)ブロック要素しか子供にしないのと(2)インライン要素しか子供にしないのと、(3)特別な要素しか子供にしないのと、(4)ほとんど全ての要素を子供にできるものがあって、(1)はbodyやnoscriptやblockquoteで、(2)はh1とかpとかaddressで、(3)はulとかtableとかで、(4)はliやdd (どちらも%block;には含まれていないのでブロック要素として教えるのは不適当か?) やdivがあると。ここに挙げたのは「引用段落」だとか「大見出し」だとか「テーブル」だとかみたいな文章を構成する大きな枠組みで、これがブロック要素。インライン要素というのは、強調語句をあらわすemや上付き文字をあらわすsup、プログラムコードの断片をあらわすcodeなどのように、段落の中の一部分を指定するもの。……ってこんな説明で良いのだろうか。確かに、人に教えることは自分の無知を確認することだと思った。

ついで質問があったのが、divとかspanとかって何だという話。divは汎用ブロック要素でspanは汎用インライン要素。たとえば、この部分は日付なんだーというのをマークアップしたいときに、date要素なんてものはないので、span要素を使う。で、class属性に"date"とでも書いておく。こうすれば、「ここは日付なんだな」というのが分かる。ただし、パーサから見れば、spanはspanでしかない。パーサはvarが変数でdfnが定義語でsampが表示結果であるというHTMLで定義されている語彙は理解するが、spanやdivにどんなclassやidが指定されていても、パーサは意味を理解しない。ここら辺に約束を定めてそれに従うパーサ間で意味を共有しようというのが、今流行のMicroformatsですな。XHTMLみたいなXML言語だと話がもう1段上がって、XML的にはpだろうがqだろうがパーサはその意味を感知しないけど、XHTMLの名前空間下においては、pは段落でqは引用語句だという意味を持つ。だからこそ、「引用語句とその引用元を抜き出して一覧にしよう」だとか、「見出しを抜き出して目次を自動生成しよう」だとか「定義語を抜き出して索引を作ろう」だとかを自動にできることになっている。

いったい私は何をしゃべっているんだと思いつつ今度はCSS編。HTMLだと論理的な面からブロックだのインラインだの言ってたけど、CSSの場合はまさにレイアウト的な面からの話になる。ブロック要素は前後に改行が入って、一まとまりごとにpaddingやmarginが計算される。インラインの場合は……なんて、displayの値をいじったときにborderがどう表示されるか観察すれば分かる話か。あとFirebugのinspectモードが大活躍。

あとは、よく使うプロパティの説明をした。text-alignプロパティは段落内の文書をどちらに寄せるかを指定するので、display:inlineな要素には指定できない。逆にvertical-alignプロパティは、段落内にある高さがさまざまなインライン部品をどこ基準で揃えるかを指定するのでdisplay:inlineな要素に指定する。あとはline-heightプロパティの値に単位を指定するのと指定しないのとでどう表示が違うかとか。

みんなの関心が高いのは段組だったので、次に段組の定石について。floatを使うのとpositionを使うのと、あとinline-blockを使う手があるが最後のは現状Opera専用なので無視。floatを使う場合は、floatさせるブロックにwidthを指定する必要がある点に注意。ただ、メジャーなブラウザはwidthなしfloatを実にうまい感じにレイアウトしてくれるのが何とも。右カラムに画像があったりして右カラムの幅を一定値にしたいとなったら、HTML上先に右カラムを書いて、その右カラムにwidthをつけてfloat、左カラムは右width分プラスアルファのmarginを着けるのがセオリー。左カラムをHTML上先に書きたい場合は? どっかで妥協するしかない。

positionを使うのがその妥協のひとつ。position:absoluteなブロックにleft値とright値を指定すれば、可変長浮きブロックのできあがり。左カラムのrightが10%なら右カラムの左マージンを90%にすればいいし、左カラムのrightが10emなら右カラムはwidthを10emにしてfloat:rightさせればOK。ただ、私としてはあんまりpositionを使いたくないけど別にこだわりません。うまく使えばレイアウト崩壊も防げましょう。私があまり使いたくないのは、Googleキャッシュとかで見られると上方向にレイアウトが崩れるからだけど、そんなに重視すべき理由ではない。

で、結局何を話せばよかったのだろうか。なんか、教材代わりに使える良質丁寧なHTML/CSSサイトがあると良いな。ただのリファレンスじゃなくて体系立てて1から読めるようなやつ。探すか。

タグ
HTML

はてダに<!--~-->を書くと記事別ページでその部分が消える

public static void mainを読んでいたら

<script type="text/javascript">
</script>

<script type="text/javascript">
</script>

と追加したら日本の広告が出るようになりました。 「AdSense コードを変更しないでください。」って書いてあったのですが、XHTML的には

<script>
<--
.
.
.
-->
</script>

のような書き方はできないので、外部ファイルで参照できるようにしてもらえるとありがたいです。

とあって、beforeとafterで何も変わっていないじゃんと本人に訊いたら本人も驚いていた。

トップページの最近の日記を見ると

<script type="text/javascript"><!--
google_ad_client = "hogehoge";
google_ad_width = 728;
.
.
.
-->
</script>

<script type="text/javascript"><!--
google_language = 'ja';
google_ad_client = "hogehoge";
google_ad_width = 728;
.
.
.
-->
</script>

と追加したら日本の広告が出るようになりました。

と、本人の意図した表示結果が出てきた。トップページのと個別ページのとで記法の解釈方法が違うのか? 最後のコード片だけちゃんと見えていたのは、"<"と"--"の間に"!"がなかったからで、追加したらちゃんと(?)このコード片も個別ページのから消えた。

タグ
HTML

OperaのXMLパーサってすごかったのね

OperaにXMLファイルを読ませるとベタテキストが出てくる。フィードだと「新規購読」というダイアログが出るけれども、画面に表示されるのは容赦ないベタテキストだ。IEやFirefoxにスタイル情報のないXMLを渡せばドキュメントツリーを表示してくれるのと対照的で、どうもOperaはXMLにやる気がないのかと勝手に思っていた。

だが、整形式でないXMLを投げた場合、Operaのエラー表示が圧倒的に見やすいことに最近気づいた。たとえば、以下のようなXMLをブラウザに表示させてみる:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <hoge>あああ</hoge>
    <hoge>いいい
    <hoge>ううう</hoge>
</root>

Firefoxだと:

XML パースエラー: タグの対応が間違っています。終了タグが必要です: </hoge>
URL: file:///D:/test.xml
行番号: 6, 列番号: 3:

</root>
--^

IEだと:

XML ページを表示できません 
XSL スタイル シートを使用した XML 入力は表示できません。エラーを訂正してください。 [更新] ボタンをクリックするか、または後でやり直してください。 


--------------------------------------------------------------------------------

終了タグ 'root' が開始タグ 'hoge' と一致していません。リソース 'file:///D:/test.xml' の実行エラーです。ライン 6、位置 3

</root>
--^

どちらも、6行目に問題があると言ってくる。だが、では</hoge>を追加しようとしても、いったい何行目のhoge要素が閉じられていないのか分からないのだ。でもOperaは違う。

エラー!
XML の解析に失敗しました

XML の解析に失敗しました: 構文エラー (行: 6, 文字: 0)

HTML ドキュメントとして再解析する
エラーmismatched end-tag
仕様http://www.w3.org/TR/REC-xml/
  1: <?xml version="1.0" encoding="UTF-8"?>
  2: <root>
  3:     <hoge>あああ</hoge>
  4:     <hoge>いいい
  5:     <hoge>ううう</hoge>
  6: </root>

と、何行目のhoge要素のせいで6行目のエラーが発生したのかを強調表示で教えてくれる。これは6行しかないから目視で分かるけど、インデントなしで千何行もあったら人間の仕事じゃなくなるわけで、Operaのこの挙動は大変ありがたい。

Xercesも

[Fatal Error] :6:3: The element type "hoge" must be terminated by the matching end-tag "</hoge>".

にとどまる。何行目のせいで整形式になっていないのかをちゃんと教えてくれるパーサってOperaくらいなのかなー。

ちなみに、不正なXMLにも対応しているパーサでこういうXMLを読ませると、以下のようになる。

CyberNeko HTML Parserの場合は (以下mainメソッドが例外をスローしてたりXMLをStringから読んでいたりしてやる気のないソースなので注意):

package net.txqz.test.xml;

import java.io.IOException;
import java.io.StringReader;

import org.cyberneko.html.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class NekoTest {
    public static void main(String[] args) throws SAXException, IOException {
        String xml = "<?xml version='1.0' encoding='utf-8'?>\n<root>\n<hoge>あああ</hoge>\n<hoge>いいい\n<hoge>ううう</hoge>\n</root>";
        DOMParser parser = new DOMParser();
        parser.parse(new InputSource(new StringReader(xml)));
        Document document = parser.getDocument();
        NodeList nodes = document.getElementsByTagName("hoge");
        for(int i = 0; i < nodes.getLength(); i++){
            Node node = nodes.item(i);
            System.out.println(node.getNodeName()+":"+node.getTextContent());
        }
    }
}

出力結果は:

HOGE:あああ
HOGE:いいい
ううう

HOGE:ううう

ShaniXmlParserの場合は:

package net.txqz.test.xml;

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class ShaniTest {
    public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException{
        String xml = "<?xml version='1.0' encoding='utf-8'?>\n<root>\n<hoge>あああ</hoge>\n<hoge>いいい\n<hoge>ううう</hoge>\n</root>";
        System.setProperty("javax.xml.parsers.DocumentBuilderFactory","org.allcolor.xml.parser.CDocumentBuilderFactory");
        System.setProperty("javax.xml.parsers.SAXParserFactory","org.allcolor.xml.parser.CSaxParserFactory");
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

        Document document = builder.parse(new InputSource(new StringReader(xml)));
        NodeList nodes = document.getElementsByTagName("hoge");
        for(int i = 0; i < nodes.getLength(); i++){
            Node node = nodes.item(i);
            System.out.println(node.getNodeName()+":"+node.getTextContent());
        }
    }
}

出力結果は:

hoge:あああ
hoge:いいい
ううう
hoge:ううう

Jericho HTML Parserの場合は:

package net.txqz.test.xml;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;

import au.id.jericho.lib.html.Element;
import au.id.jericho.lib.html.Source;

public class JerichoTest {
    public static void main(String[] args) throws IOException {
        String xml = "<?xml version='1.0' encoding='utf-8'?>\n<root>\n<hoge>あああ</hoge>\n<hoge>いいい\n<hoge>ううう</hoge>\n</root>";
        Source src = new Source(new StringReader(xml));
        List<Element> list = src.findAllElements("hoge");
        for(Element element : list){
            System.out.println(element.getName()+":"+element.extractText());
        }
    }
}

出力結果は:

hoge:あああ
hoge:
hoge:ううう

Jericho HTML Parserは w3c DOMを使わずに独自の形式でHTMLやXMLをパースするのだけれども、不正なXMLもパースできるのがウリなのにこの方法で「いいい」を抽出できなかった。やりかたが悪い? いやまぁ整形式でないのが一番悪いのですが。ほかのパーサも「いいい」だけ抽出するのは不可能で、「いいい」と「ううう」がセットになる。それは、パーサがこの適当なXMLのDTDを知らないから当然の処理。HTMLで<ul><li>あああ<li>いいい<li>ううう</ul>とかなっている場合は、HTMLパーサと名乗っている以上li要素の暗黙の終了タグをちゃんと補完してくれることでしょう。

あと、いま知ったのだけれども、XML宣言ってversionを必ず最初に指定しないといけないのね。encodingを先に指定したら[Fatal Error] :1:23: The version is required in the XML declaration.とXercesに怒られた。Xerces厳しすぎワロタと思ったら仕様[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'って書いてあった。ふつうXMLの属性は登場順序に意味がないので、宣言もそうだと思い込んでいた。いまさらー。

XMLはツリー表示されることを規定しないのでOperaはCSS初期値で表示してる(cf. http://kuruman.org/old_diary/200608#D19-01 )。パースエラーの開始箇所候補を挙げてくれるのはありがたいよね。

なるほど。やっぱりはOperaすばらしいですね。

タグ

Google Japan Blogが句読点を文字参照している件

Google エンジニア インタビューがはてブかどっかに上がっていて興味深く読んだのだが、なんで「?」とか「、」とか「。」とかを実体参照文字参照しているのかよく分からん。システムの仕様なんだろうけど、なんでそんな仕様にする必要があるのかよく分からん。それでいて">"はそのまま書いてあるんだよなぁ。別に"<"さえ実体参照しておけば">"は必ずしもエスケープしなくてもいいのかもしれないけど、なんか気持ち悪い。←なんという印象論。

タグ
HTML

BODY直下をDIVで揃えたい症候群

上のソースでは、liのリスト項目をulで「順序の無い箇条書き」と明示しているのに、それを更にdiv要素としてマークアップしています。ほとんどの要素に対してid属性やclass属性は付けることが出来ますので、これなら直接ul要素にidを付加させましょう。

確かにその通りだ。実際に私が今まで書いてきたHTML文書の中にもここで例示されているようなマークアップが何回か出てきていた。

なんとなく、BODYの直下にDIVとそれ以外が混ざるのが嫌だったんだと思った。もちろん文法上はそのような制限はない。ただ、なんとなくBODY直下にDIVが1つでも出てきたら全ての非DIV要素をDIVで包まないと落ち着かなかった。

例だと

<div id="navi">
 <ul>
  <li><a>About</a></li>
  <li><a>Profile</a></li>
  <li><a>Gallery</a></li>
  <li><a>Links</a></li>
 </ul>
</div>

よりも

<ul id="navi">
 <li><a>About</a></li>
 <li><a>Profile</a></li>
 <li><a>Gallery</a></li>
 <li><a>Links</a></li>
</ul>

の方が良いですよねという話だけど、ナビゲーションリストに先駆けて見出しを起きたいなら、むしろ

<div id="navi">
 <h2>ナビゲーション</h2>
 <ul>
  <li><a>About</a></li>
  <li><a>Profile</a></li>
  <li><a>Gallery</a></li>
  <li><a>Links</a></li>
 </ul>
</div>

というマークアップが適切になるような気もする。結局はその場その場で適切に判断することになる。

あと、はてなダイアリーのはてなモジュールを使うと

<div class="hatena-module">
<div class="hatena-moduletitle">最近のコメント</div>
<div class="hatena-modulebody">
<ul class="hatena-recentcomment">
<li><a href="/denken/20070610/1181474055#c1182612946">2007-06-10</a> な</li>

<li><a href="/denken/20070401/1175391705#c1175397175">2007-04-01</a> kiwofusi</li>
<li><a href="/denken/20070329/1175125902#c1175158985">2007-03-29</a> harukonbu</li>
<li><a href="/denken/20070329/1175125902#c1175156359">2007-03-29</a> umekoumeda</li>
<li><a href="/denken/20070321/1174441534#c1174447026">2007-03-21</a> umekoumeda</li>
</ul>
</div>
</div>

などのようなHTMLが出力されるが、これはDIV厨めいている。モジュールのスタイリングを一律にするためにhatena-modulebodyというクラスのDIV要素がUL要素をラップするようになっているが、厳密には不必要なDIV要素のはず。hatena-moduletitleについてはさらにひどいが、これはどの見出し要素を使うべきかは文章全体を見ないと決定できないために仕方なくやっているのかな。XHTML2.0のh要素が楽しみですね。

タグ
HTML

XHTMLのContent-type

手動でマークアップするかぎり、やっぱりContent-typeにapplication/xhtml+xmlを指定するのはためらわれる。ぜったい間違えるし。この間みたいに。text/htmlなら間違えてもフールブルーフが働くかなーなんて。

RSSみたいに機械的にマークアップするようなリソースなら、プログラムが間違っていない限りほぼ完全に妥当なXMLを吐けるから、安心してapplication/rss+xmlとか名乗れるし、名乗らないといけない。一時期この日記は手書きに近い形でRSSを提供していたんだよねぇ。今じゃ考えられない。

そうなると、Content-typeにtext/htmlを指定するのをオススメしていないXHTML1.1は使うわけにいかず、XHTML1.0 Strictを採用することになるわけだ。ただ、XML応用言語で文書をマークアップする以上、やはりXMLツールで処理することを念頭においていることになる。それはXHTMLが整形式であることを前提とした考えだ。その一方、手書きしたXHTMLが間違っているかもしれないから、私はtext/htmlなXHTML1.0を書いている。まったく原理主義的でない。ていうか原理主義的だと疲れるからこれでいいと思った。最大公約数。

タグ
html

あんまりマークアップされないHTML要素

はてブにAjaxよりも先に覚えておくべき 忘れられた5つのHTMLタグという記事があがっていた。まぁソースコードを書かない人がvarだのcodeだのsampだのを覚えてもしょうがないけれども、dfn要素の明示はできる限りみんなやるべき。みなさんがどんなDTDに従ってHTMLまたはHTMLもどきを書いているかは分からないけど、少なくともhttp://www.w3.org/1999/xhtml名前空間においてdfn要素は被定義語をあらわすというのが重要。SEOがどうとかそういうレベルじゃない。span要素にどんなクラス名をつけてもなんら意味がないけれど、dfn要素にはdefinitionという明白な意味がある。単に強調とかSEO対策とかしたいならem要素として明示すればいいんでないの? 効果があるかは知らないけど。

で、見出しをh1要素とかでマークアップしておけば目次を自動生成できたりするのが嬉しいわけだけれども、被定義語をdfn要素としてマークアップすると何が嬉しいか。まず索引を自動生成できるのが嬉しい。昔日記をXMLで書いていたときはXSLTを使って索引を生成していた。これはXSLTで書いたから、同じことをXHTMLでやっているブログがあればそこのデータもマージできる。はてダとかキーワードでつながるコミュニティは、辞書にある単語ならなんでもつながってしまうのが却ってわずらわしいかもしれない。被定義語でつながるコミュニティがあってもいいなと思った。謎。

タグ
html

正しくHTMLを書こうと心がけている人に5の質問を

正しくHTMLを書こうと心がけている人に5つの質問に回答。

HTML文書を制作する際に使用しているプログラムをお答えください。(Webプログラムも含む)

昔はTTTEditorを使っていました。Ctrl+pで<p></p>が出るなどとショートカットを設定できるので、なんかいろいろ設定してました。いまは、EmEditorとかの一般的なテキストエディタに書いてコピペしてます。

採用しているDTDとその理由をお答えください。

XHTML1.0 Strictにしています。前はXHTML1.1でした。ruby要素を使いたかったから。ただ、面倒であることや技術的な問題などでメディアタイプをapplication/xhtml+xmlにせずにtext/htmlにしてました。いまは、別にXHTML1.1なんて使わなくてもXHTMLであればよい (XML処理系でいろいろできる) のでXHTML1.0にしています。Strictなのは、別にTransitionalな要素や属性を使う必要に迫られていないからです。

何故正しくHTMLを書いているのですか?

正しく書かない理由がないからです。でも、たまに間違って正しくないHTMLになっちゃうこともあるよNE。

W3CとWHATWG、どちらに期待してますか?

後者のことをよく知らないので答えにくいですけど、別にW3Cに絶望していたりはしません。

あなたにとってHTMLとは何ですか?

よく普及したマークアップ言語。

というか、アレですね。質問ネタといえば100質のマークアップの話が思い出されますね。あのとき私は

  1. これは1番目の質問から100番目の質問という順番に意味があるリストなので、是非ol要素としておきたい
  2. 一つの質問に一つの回答が付くから定義リストであるような感じなので、是非dl要素としておきたい
  3. すると、ol要素の子要素にdl要素が来て、某方面およびその周辺で良く見かけるマークアップとなる

なんて書きました。今は面倒なのでそのままdl-dt-ddです:-)でも、dl要素にqaって値のclass属性をつけて、

dl.qa dt{
  display: list-item;
  list-style: decimal;
}

なんてやろうかな。Firefoxだとみんな0になっちゃうみたいだけど。

IEだと1,3,5……と飛び飛びになってしまう件。んー。

[righthtml5q][notvalid]liの終了タグ抜け?

直しました。

タグ
HTML

なぜ人はこんなにひどいHTMLを書くのだろう

<DIV CLASS=MNBODYf>
  <TABLE WIDTH=150 BORDER=0 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>
    <TR>
      <TD COLSPAN=3>
        <FORM NAME=finder METHOD=GET ACTION=http://www.exblog.jp/search/>
          <INPUT TYPE=HIDDEN NAME=blogid VALUE=1000036104>
      </TD>
    </TR>
    <INPUT TYPE=HIDDEN NAME=t VALUE=0>
    <TR>
      <TD WIDTH=105 ALIGN=LEFT>
        <INPUT TYPE=TEXT NAME=q SIZE=15  CLASS=TXTFLD>
      </TD>
      <TD WIDTH=5></TD>
      <TD WIDTH=40 ALIGN=LEFT>
        <INPUT TYPE=SUBMIT VALUE="検索" STYLE="WIDTH:40;HEIGHT:20;">
      </TD>
    </TR>
    <TR>
      <TD COLSPAN=3>
        </FORM>
      </TD>
    </TR>
  </TABLE>
</DIV>

(見やすいように改行とインデントを加えました)

エキサイトブログはXHTMLを名乗っておきながら空要素を閉じないし、上に示したように整形式を書く気もさらさらないし、なんかクローラ対策かしらと勘ぐってしまいたいほどひどいHTMLになっている。なんなんだこれは。前にspan要素のなかに<p/><p/>というのが複数出てくるという二重三重に誤ったHTMLを見たことがあるが、何系の発想でこういうものが出てくるのか、本当に不思議でならない。平成の時代はあらゆる困難が科学の力で解決しているとされているが、魑魅魍魎はこんな形で私たちの前に姿を現しているのだ。

タグ
HTML
© 2001-2008 Chisa YOUZAKA. Some rights reserved.