ものがたり(旧)

atsushieno.hatenablog.com に続く

XslCompiledTransform

新しいVS 2005のMSDNドキュメントのAPI Reference、相変わらず古いんですけど。いいかげんXQueryCommandとかXsltCommandとか、消した方がいいと思いまーす。

さて、というわけでMSDNドキュメントを突っついても見あたらないXslCompiledTransformは、実はSystem.Data.SqlXml.dllという、もはやcompiled XSLTのためだけにしか存在しないdllの中に入っているようです。

ざっと見た感じ、この辺は良い仕事をしているみたい。具体的に言うと、おそらくサッサと捨ててしまいたいであろう現状のXPathExpressionやXPathNodeIteratorは、ほぼ使われていないでしょう(XsltSettings.AllowScriptが使われておらず、スタイルシート中でextension elementsが使われていなければ、XPathNodeIteratorは使われないかも)。もともとはXsltCommandだったのだから、それを既存のXslTransformと摺り合わる作業を行ったということです。めんどくさいですね。こういう仕事はしたくないです。エライ。とはいえ、XslTransformとXslCompiledTransformには、基本設計として動作の互換性が無いようです。とりあえず使ってみていくつか気付いた点を書いてみます。

(1)エラー回復

たとえば要素にchild itemを追加した後で属性を追加するのはエラーで、属性を追加しないで回復することもできるんですが、XslCompiledTransformではそれを許しません(XslTransformでは許している)。同様に、属性の中に要素を内容として追加するのはエラーなんですが、XslTransformでは単に無視していたんですね。これもXslCompiledTransformではNGです。

で、実用上どっちのがマシかと言ったら、XslCompiledTransformの方が、数段まともです。なぜなら、XslTransformで動いたスタイルシートは、実はエラーを含むような内容かもしれないのです。ぶっちゃけ、XSLT 1.0の「まあどっちでもいいことにしよう」っていう仕様がイケてないんですが。

(2)strip-spaceとTransform()の引数

スタイルシート中にxsl:strip-spaceが指定されていると、XslCompiledTransformはIXPathNavigableを受け付けてくれません:

System.Xml.Xsl.XslTransformException: Whitespace cannot be stripped from input documents that have already been loaded. Provide the input document as an XmlReader instead.

(これは以前ここにも書いたんですが)何でかというと、最初から処理されないと分かっている空白ノードは、XPathNavigatorを引数にしてしまうと、こいつは読み取り専用なので削除できないんですね。でも、無駄なんです。最初からXmlReaderを引数にしておけば、読み込む側の都合でいくらでもハナから相手にされない空白ノードをstripできるわけです。

じゃあXPathNavigatorを処理するにはどうすれば良いんだよ?という話ですが、ReadSubtree()を使いましょう。って、ツリー構築がなにげにパフォーマンス的にはでかい問題なんですけどねー。

その他

あと、name属性がattribute value templateになっていても、prefixはコピーしないようにしたみたいだったり、ローマ数字ベースのformat-number()がフツーになっていたりとか、いろいろ改善というか変更されているみたいですが、とりあえずざっと見、良い感じです。

処理速度ですが、以前のXsltCommandのように、いかにも事前コンパイルをしています、という感じではなくなりました。おそらくDynamicMethodとかいろいろ駆使しているんでしょう。変換処理の方は、Clone()でオブジェクトを生成しまくっていたiteratorが全部structになったので(これはmsxsl:scriptとか使っていたら使われないかもしれません)、これは軽くなっていて当然でしょう(そういえば昔、XPathNodeIteratorのClone()のコストは大したこと無い、とか言ってたどっかのMSの中の人だかMVPだかもいましたが)。

で、これ、実装しなきゃダメ? うーん、めんどくさいなあ…