暇っちゃ暇ですけど、激しく時間が欲しい。はぁ。
暇かつ忙しい
箱デザイナー
メレンゲ
夢。複雑な建物。姉
2005
目標的なものはあるわけですが、経済的理由で始められるのがいつになるのか謎。
書くとやる気がなくなってしまうし、タイミングが合わなくてもモチベーションがかなり落ち込むのでできるだけ早く、できれば今日からでも始める必要がある。去年三年間までの糞さを取り戻す必要がある。今年は変える必要がある。
俺は今だいぶ鼓動が早い。よく思うんだけれど、周囲の人間ってコアは部分でどれだけ役に立つかっていったら殆ど役に立たないじゃないか。趣味の部分だけだ。コアな部分は自分が考える必要がある。バリエーションの少ないアドバイスが溢れている。つまらない。今寝る前に書いている。朝起きて今のモチベーションがどうなるかわからない。だからできるだけ思いつく限り書いておく。
うさんくさい。信頼って無理
フラグメントプレビュー
同一文書のフラグメントへのリンクでプレビュー、とか……邪魔か便利かのぎりぎり狭間ぐらいなのでまだ適用はしてない。微妙。
適当に書いて動作したのは Opera, Gecko だけ……IE は何故か動かない。でも Opera は動的なレンダリングが苦手 (糞遅い) のでハズしてみてみた。
DOM の Range とか使ってみちゃう?とか思ってたけど IE では見事に実装されていないみたいなので普通に cloneNode() して CSS の overflow あたりで適当に表示制限。まぁ結局 IE で動いてないわけですが!
なんかの勘違いだったもよりで、IE でも正常に動作してた。キャッシュか何か読んでたカナ。
スタイルを書き換えて適用してみた。このセクションの画像とは違う。スモールスクリーンモード (謎)
Opera (7.6 preview) でもう一回試してみたら割りと普通になってたので適用してみる。
ただ、ネゴシエーションされたファイルの扱いが違うので Opera では一部プレビューされない。Opera は href="" というリンクのときネゴシエートされた後のファイル名を使うのでうまく処理できない。ぶっちゃけどうにもできないので仕様。
2004.fpl
結果ツリーフラグメントの誤解
2004年12月の指向性メモ で言及されてるのを読んでもう一度仕様書を読み直してみる。
Variables introduce an additional data-type into the expression language. This additional data type is called result tree fragment. A variable may be bound to a result tree fragment instead of one of the four basic XPath data-types (string, number, boolean, node-set). A result tree fragment represents a fragment of the result tree. A result tree fragment is treated equivalently to a node-set that contains just a single root node. However, the operations permitted on a result tree fragment are a subset of those permitted on a node-set. An operation is permitted on a result tree fragment only if that operation would be permitted on a string (the operation on the string may involve first converting the string to a number or boolean). In particular, it is not permitted to use the
/,//, and[]operators on result tree fragments. When a permitted operation is performed on a result tree fragment, it is performed exactly as it would be on the equivalent node-set.
強調した部分が重要らしい。最初の強調がややこしい。原文引用なのは訳文がまたさらにややこしいから (謎)
結果ツリーフラグメントに使える操作はノード集合の一部 (最初の強調) でその許される操作ってのは文字列にできるやつだけ (二つ目の強調)。あとはその後に書いてある通り、/ とかの演算子は使えない。
結局、結果ツリーフラグメントが格納されている $rtf がある場合において <xsl:apply-templates select="$rtf/child::node()"/> は XSLT1.0 的にはエラーらしい。
そんなこんなで、XSLT1.0 でマトモな変換を書こうとするとかなり冗長なことをせざるを得ない状況が生まれるみたいです。めんどくさー
関係ないけど、どういう経緯でこういう制限がついたんだろう。
2004 として
今年は (前にも書いたけど) 異様に長く感じる一年だった。IRC で #汚れの巣 に突っ込んだのも、ヘッドフォン娘のアレ を書いたのも、去年かそれより前に感じる。それぐらい長く感じた。でも長く感じる割に起きている時間が少なかった気もする。殆ど寝てた。
この一年で何が変わったのか。少し技術と知識は向上しただろうけど、基本的なところでは何が変わったかよくわからない。諦めがはやくなったぐらいか。あとは常に身近な誰か (自分も含めて) が死ぬような予感がつきまとって気持ち悪かった。
キーワード。想像力とうさんくささ。とにかく頑張れなんて言葉をたやすく言わない。気付くと嫌いな言葉がいっぱいある。軽くどうでもいいけど困るのは自分だからなっていうフレーズはうさんくささがレベル最高ぐらいある気が。
とりあえず卒業はできそうでなにより。その後どうなるかはわからんわけだけど?
めんどくさ
Ruby or PHP
ある関数の比較
function _load_flavors() {
$xns = $this->_xpc->xpath_eval("/config:config/config:flavors/config:flavor");
foreach ($xns->nodeset as $node) {
$ext = $node->get_elements_by_tagname("extension");
$ext = $ext[0]->get_content();
$content_type =$node->get_elements_by_tagname("content-type");
$content_type = $content_type[0]->get_content();
$this->flavor[$ext] = $content_type;
}
$this->default_flavor = $this->_xpc->xpath_eval_expression("string(/config:config/config:flavors/@default)");
$this->default_flavor = $this->default_flavor->value;
} private
def load_flavors
@flavors = {}
@doc.elements.each("/config/flavors/flavor") do |ele|
@flavors[ele.text("extension")] = ele.text("content-type")
end
@default_flavor = @doc.root.elements["flavors"].attributes["default"]
end でもここで使ってる Ruby の REXML というパーサは名前空間をあんまり (ほとんど?) 考慮してない (だから接頭辞がついてない。読み込んでいるドキュメントはデフォルト名前空間でやっていて接頭辞がないから) REXML は XPath とか使えるしイケてるけど、やっぱ微妙な部分がいくつかあるわけです。
PHP は書いた気になれる。んで後から読むと読み難い。実際には一回の代入が二行になっていたりするから。だからといって一行に纏めても読み難い。
PHP4 には例外もない。5 からあるけど、5 でやっと?みたいな勢い。
日記スクリプト思考
XML は中間データとして使うようにしてみる。もちろんデータを XML で書いてもいいし、てきとーにデータベースから XML 生成するような実装をすればデータベースを元データとして使えるように。
例えば XMLDB みたいなクラス作っといて、get_latest_xml($num), get_month_xml($year, $month) みたいなメソッドを実装 (できればインターフェイスだけ定義したクラスを作っておきたいけど PHP4 じゃ無理くさい) しとく。それぞれのメソッドは決まった XML を返す。
スクリプトは設定に応じてどのクラスを使うかを決めてインスタンス化&メッセージを投げて XML を得る。あとはそいつを XSLT エンジンに丸投げして、結果を設定した Content-type で出力。
別に PHP でなくてもいいんだけど、Ruby は三郎拡張がローカルで動かないから……
カテゴリ? タグ?
PHP わけわからん。UNKE PHP
なにやらeval('$db = new ' . $config->dbclass . '($config, $lang, $tags);'); と $db = new $config->dbclass($config, $lang, $tags); は同じっぽい。もちろん $config->dbclass はただの文字列。ナンダコレ。
それと $ext = $node->get_elements_by_tagname("extension")[0]->get_content(); がパースエラーって何よ。前にも書いた気がする。
$ext = $node->get_elements_by_tagname("extension");
$ext = $ext[0]->get_content();
上記のようにしないとダメ。
書いてて途中で PHP 捨て実行のために sablot/Ruby とか sablotron を一からやりなおしたりした。まー無理だったわけですが orz
つまり、PHP では汚いコードを心置きなく書けるわけです。あら素敵?
PHP でコードを書く理由って Sablot と mod_php のためだけなんだよね。ホント。関数の命名規則もバラバラだし、謎が多い。
もういくつ寝ると
25 日終わったからもとのスタイルに戻したよ。
クリスマスにまず損しない (金は減るけど) 投資 (謎) して、ドレぐらい返ってくるかなぁ、とか思ってみたけど損しない分しか返ってこなかった。残念。まぁ全然いいんだけどももももも。
もっと寒いスタイル作りたいなぁ。モニターに息吹きかけると白くなるぐらい寒いスタイルシート書きたいなぁ。スポットライトと観覧車ってとこかなぁ。遊園地って人が多くて好きじゃないけど、観覧車っつう言葉の響きは好きだ。母親の実家に行く途中古ぼけた遊園地があって、その中に観覧車があるんだけど、幼稚園生のときその観覧車が動いているかどうかを何故か毎回確かめてた。この前通りかかったとき遊園地自体が潰れてた。ついでにもう通りかかることもなさそうだ。
まーとにかく Helvetica ってフォントの名前だよね。
日記の名前空間
- 日記データの名前空間が適当すぎる。ほぼ XHTML で書いている本文も XHTML の空間じゃない。作ってるときは名前空間いちいち書くのが面倒だったらからそうしたんだけど、今になってみるとキモい。
- 変換用のデフォルトテンプレートあたりがちょっと気持ち悪い。統一感がないのでもうちょっと blosxom 的にしたい。
- 設定が .inc とかに入っていて気持ち悪い。スキン的な設定はスクリプトから完全に分離すべき。
- 本体とは違う (スキン) けど abbr 要素とかを補完する辞書の語彙がやっぱ微妙に気持ち悪いのでスキーマをちゃんと定義しておきたい。一番めんどい
Taglibro を少し作り直そうと思い始めたわけだけど、実際日記本文に使う空間を何にするかとかで悩んでる。今は殆ど XHTML 1.0 と同じだけど、ホントにコレでいいかなぁとか何とか、だからといって XHTML 2.0 はまだ勧告されていないし、XML Schema の場所も決まっていない (TBD) ……一応どっちでもいけるようにはしてみてるけど、実際書くのはどっちかだし。
それと、できるだけ自然に書くため (つまりミスタイプを少なくするため) 名前空間接頭辞をできるだけ付けない様にしたい。ということはデフォルト名前空間を多用する (セクションごとに名前空間書く) ことになるけど、XML Shema の仕様を眺めてみる限り、実態参照の宣言方法がない。というか DTD でいうところの内部サブセットをどうやってやればいいか分からない……名前空間を省略したいだけの参照をスキーマで宣言するのはおかしいから内部サブセット的なものが必要。実態参照だけ DTD 使うのがいいかなとか思ったけど Validator がエラー出す (DTD で要素が宣言されていないよ!っていう) のでダメっぽい。併用すること自体アレだし……
夢、坂、広場
書こうと思ったんだけどうまく説明できない。たぶん前にも少し見たことがある。
坂がある。高床式の木で出来た小屋が沢山ある。そこに行くために坂がある。木で出来た少し大きめの小屋がある。坂の下には近代的でかなり大きい (とはいえ面積が広いだけで高さはそんなでもない) 建物がある。建物の一階部分はまるまる外で、グレイッシュレッドの柱がたくさん立ってる。二階以上の部分の壁の色はクリームホワイト。たくさん白いテーブルがある。料理が置いてある。人がいっぱいいる。顔見知りばっかりだ。
いくつかやること (忘れた) があった。不安がいくつかありつつもやることは無事に終わった。やることは大き目の小屋で行った。
他には、ロッカー、携帯電話、パーカーぐらい。
XSLT で行をマークあっぴ
汎用っぽいテンプレ作っていたら、XSLT だけで一行ごとに l 要素とかソレっぽいのでマークアップできることに気付いた……っていうかアレだ。
<xsl:template name="split">
<xsl:param name="value"/>
<xsl:param name="splitter"/>
<xsl:param name="element-name" select="'t:item'"/>
<xsl:choose>
<xsl:when test="contains($value, $splitter)">
<xsl:element name="{$element-name}">
<xsl:value-of select="substring-before($value, $splitter)"/>
</xsl:element>
<xsl:call-template name="split">
<xsl:with-param name="value" select="substring-after($value, $splitter)"/>
<xsl:with-param name="splitter" select="$splitter"/>
<xsl:with-param name="element-name" select="$element-name"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$element-name}">
<xsl:value-of select="$value"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:call-template name="split"> <xsl:with-param name="value" select="'aaa#x0a;bbbb#x0a;cccc#x0a;z'"/> <xsl:with-param name="splitter" select="'#x0a;'"/> <xsl:with-param name="element-name" select="'l'"/> </xsl:call-template>
正規表現使いたい……
Opera で色づけ
Opera 7.54 でコードが途中まで消えるっつう指摘を受けたので、navigator.userAgent.match(/Opera/) && navigator.userAgent.match(/7\.54/) が真だったら色づけしないようにした。消えるのは致命的杉。
たぶんドキュメントフラグメントに大量にノード突っ込んで既存のノードと置き換える部分が原因で最初のほうがレンダリングされなくなるんだと思うけどよくわからない。リロードするたびに消える範囲が変わる;
Namazu Cron
またメールが来なくなっていたので確認。インデクシングされていない。NMZ.lock2 は最初なかったのに、CGI 経由で実行したらNMZ.lock2 が残っています
というエラーとともに出来た。自分で作って自分でえらー吐いてるのか……?
仕方ないのでまたインデックス全部削除。
XSLT の XPath の
ネームスペース宣言の集合は、式が現れるアトリビュートを持つエレメントのスコープに含まれるものと同じである。この集合には、XML ネームスペース勧告 (XML Namespaces Recommendation) [XML Names] が必要とする、暗黙的に示されたプレフィックス xml の宣言も含まれる。デフォルトのネームスペース (xmlns を用いて宣言されたもの) は、この集合の一部ではない。
とか書いてあったりする。ソースツリーのデフォルトネームスペース URI が null (特に名前空間を全く宣言していない場合とか) 以外の時は絶対にプリフィックス無しではマッチとかしない。
<foo> <bar>baz</bar> </foo>
この場合に string(/foo/bar) = 'baz' は true。
<foo xmlns="http://foo/"> <bar>baz</bar> </foo>
この場合は string(/foo/bar) = 'baz' は false。/foo/bar は何も選択しない。例え XSLT 側のデフォルト名前空間が http://foo/ であっても何も選択されない。xmlns:f="http://foo/" とかやって /f:foo/f:bar ってやらなきゃいけない。
で、困るっていうかよくわからんのはソースツリーのデフォルトネームスペースと結果ツリーのデフォルトネームスペースを同じにしたいときなんですよと。必然的に xmlns:f="http://foo/" と xmlns="http://foo/" とか (順番も重要) やるわけですよ。exclude-result-prefixes="f" とかやるわけですよ。そうすると仕様書的に正しいかはよくわからないけど Sablotron の場合はどっちとも (xmlns, xmlns:f) 消えるんですよ (msxsl では大丈夫)。で、どうすんねんと哀さんと話していた次第(謎
xsl:namespace-alias とか利用すんのかなぁと思っていくつかソレっぽく書いてみたけどダメだった……なんかセオリー的なやり方ってないのかな。
XSLT と DOM との相違
XSLT では属性ノードとその親ノード (要素) との関係は片方向……属性ノード側からは @attr[. = ../../@attr] (省略しない場合: attribute::attr[self::node() = parent::node()/parent::node()/attribute::attr])) とかいう風に親がちゃんと親に見える (っておかしいな) けど、その親からは (attribute:: としているように) 軸が違う。ここで親から child::attr とアクセスできたら困るわけだけど、ややこしい。どうも俺は属性を子ノード的にイメージしていて attribute っていう軸がイメージしにくい。
DOM の場合は属性に親ノードはなく (parentNode は null) ownerElement に親要素が入ってる。軸が完全に分離してるっつうのかなぁ。DOM だとあんまり混乱しない。ただのプロパティでしかないからかなぁ。
XSLT の場合も DOM っぽい考え方をすればいい気がするのでちゃんと書いて、どこがどう違うかを考えてみてる。軸をプロパティと考えればいいの鴨。
// わけわかんコードだ(w
contextNode = current();
with (contextNode) {
contextNode = child["*"];
with (contextNode) {
contextNode = attribute["attr"];
with (contextNode) {
text();
}
}
}
結果ツリーフラグメント
注意 これは間違ってるかもしれない。実際に実装を使って確かめたわけじゃない。今はめんどくさくて確かめたくないので覚書的なもの。
変数バインドエレメント (xsl:param, xsl:variable) では select でノードセット格納するときと、子要素にテンプレートを書いてごちゃるのとでは違うらしい。後者は結果ツリーフラグメント (Result Tree Fragment) になる。これはルートノードを含む。(select の場合でもルートノードを含むように選択すればルートノードは含まれる。例えば document() を単体で使えば必ずルートノードがノードセットの入る)
<xsl:variable name="foo" select="/bar"/> <xsl:apply-templates select="$foo"/>
<xsl:variable name="foo"> <xsl:copy-of select="/bar"/> </xsl:variable> <xsl:apply-templates select="$foo"/>
前者の場合、ルートノードを含まないノードセットなので、無限ループに陥らずにちゃんとなる。後者の書き方によって $foo に格納されるのは結果ツリーフラグメントで、結果ツリーフラグメントはルートノードを含むので、(現在適用しているスタイルシートの match="/" にマッチして) 無限ループ。
結果ツリーフラグメントをノードセットと混同するとエラい目にあう。例えば Mozilla がクラッシュしたりとか。
結果ツリーフラグメントは、結果ツリーの断片 (フラグメント) を表す。結果ツリーフラグメントは、ルートノードを1つだけ含むノード集合と同様に扱われる。
変数バインドエレメントが select アトリビュートを持たず、コンテンツが空でない場合 (つまり、変数バインドエレメントが1つまたは複数の子ノードを持っている場合)、変数バインドエレメントのコンテンツが変数の値になる。変数バインドエレメントのコンテンツはテンプレートであり、このテンプレートをインスタンス化すると、変数の値が得られる。この値は結果ツリーフラグメントであり、このフラグメントはテンプレートをインスタンス化して生成した一連のノードを子に持つルートノードを1つだけを含むノード集合と同等である。
あっていれば xsl:param にノード集合を渡す。 はノード集合ではなく正確には結果ツリーフラグメントだ。まぁ扱い方的はあまり変わらないけれど……
ってことは <xsl:param name="ggg" select="'unke'"/> と <xsl:param name="ggg">unke</xsl:param> は違うんだ。実際これらを <xsl:value-of select="$ggg"/> とかやると文字列に変換されるので同じように見えるだけか。この場合前者の方が変換がなくてほんの少し高速かな。
XPath の紛らわしさ
XPath は XPath という名前だけでも誤解を招く。Path というだけにディレクトリパスとかを連想する。まぁ、ディレクトリパスとは類似点が多い。UNIX ファイルシステムにおけるルートディレクトリ (名前ナシ) と、ルートノード (展開された名前ナシ) とか、それに省略形による表記を使うとパット見ディレクトリを特定するためのディレクトリパスとなんら変わらない。‘/’ を区切りに使うのが紛らわしい。カレントディレクトリ と XSLT における カレントノード を混同しやすい。XPath にはカレントノードなんてものはない。コンテキストノード。
XPath は文字列とか数値も表現しえるので、ただたんにどっかのノードを特定する言語ではない。(とはいえ W3C 仕様書には XPath は、XML ドキュメントの一部をアドレッシングするための言語であり
とか書いてあって紛らわしい)
だめだもう寝る。