javascript で Transformer

CATEGORYjavascript
xml に xsl を適用するときに、xml-stylesheet処理命令 を使うと、
  • xsl をパースするためのコストがかかる
  • IE だと 使ってくれるな と Knowledge Base に (堂々と) 書いてある
というわけで、javascript で JAXT の javax.xml.transform.Transformer に当たることを javascript のコードで書いてみた。

本当は、ここにサンプルも含めて載せたかったのだけれど、ファイルのアップロード先が別ドメインなので、セキュリティ的にどうとかうるさいので、別のページにサンプル を置いた。


まずは、エラー処理などをガッツリ省略した IE 用と FF用のコードの比較。

■Internet Explorer (IE6 SP3 で確認)
function transformIE(xml, xsl, callback) {

    // load XSL
    var xslDom = new ActiveXObject("MSXML2.FreeThreadedDOMDocument")
    xslDom.async = false
    xslDom.setProperty("ForcedResync", false)   // use cache
    xslDom.load(xsl)

    // create XSL Processor
    var xslTemp = new ActiveXObject("MSXML2.XSLTemplate")
    xslTemp.stylesheet = xslDom
    var xslProc = xslTemp.createProcessor()

    // load XML
    var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
    xmlhttp.open("GET", xml, true)
    xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {
                if (xmlhttp.status == 200) {
                    // transform XML
                    xslProc.input = xmlhttp.responseXML
                    xslProc.transform()


                    var html = xslProc.output

                    // call back
                    callback(html)
                }
            }
        }
    xmlhttp.setRequestHeader("Method", "GET "+ xml +" HTTP/1.1");
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlhttp.send("")
}
■FireFox (3.0.10 で確認)
function transformFF(xml, xsl, callback) {

    // load XSL
    var xslDom = document.implementation.createDocument("", "", null)
    xslDom.async = false

    xslDom.load(xsl)

    // create XSL Processor
    var xslProc = new XSLTProcessor()
    xslProc.importStylesheet(xslDom);


    // load XML
    var xmlhttp = new XMLHttpRequest()
    xmlhttp.open("GET", xml, true)
    xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {
                if (xmlhttp.status == 200) {
                    // transform XML
                    var fragment = xslProc.transformToFragment(xmlhttp.responseXML, document)

                    // DOM fragment to String
                    var serializer = new XMLSerializer();
                    var html = serializer.serializeToString(fragment);

                    // call back
                    callback(html)
                }
            }
        }
    xmlhttp.setRequestHeader("Method", "GET "+ xml +" HTTP/1.1");
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlhttp.send("")
}



本質的には、両方ともあまり変わらない。
上記コードの xslProc のオブジェクトは毎回作成する必要は無くて 使いまわす ことができる。

こんなときに使えるはず。
  • ひとつの XSL を、連続していろいろな XML に適用する
  • XSL がとてもでかい
  • ひとつの XML に、XSL をいろいろ変えて結果を得る

実際に使う場合には、
  • エラー処理
  • メソッドが POST で取得する場合
  • 名前空間の汚染
など、いろいろ手を加える必要があると思うけど。


最後に、今回書いたコードを整理。
IE はなんだかんだとあるけれど、ドキュメントが MSDN に集中しているのが良いな。
MDC はサイトが重かったり、記載が抜けていたりと、何かと苦労する。
関連記事
スポンサーサイト

javascript クロスブラウザ XMLHTTPRequest

0 Comments

Leave a comment