表示されているhtmオリジナルソースの取得

[新着] TAG indexオフライン版 3.0 を準備中です



0   名前: yoro : 2007/05/22(火) 20:31  ID:ECDmC1Px sub-1h
複数半角スペースが含まれているhtmソースを取得したいと考えています。

目的
 HTMLは、複数スペースをひとつに圧縮してしまうので、
レイアウトを崩さないように<PRE>タグを挿入し対応したい
と考えています。
⇒ コンテキストメニューにて

 しかし、JavaScriptのinnerhtmlで取得できるのは複数スペースを
ひとつに圧縮した後のデータのようです。

IEのソースを表示で得られるようなhtmソースの取得方法があればご教授下さい。

よろしくお願いします。

1   名前: 匿名 : 2007/05/22(火) 20:31  ID:OF72WdCi sub-Cz
そもそも、innerHTML の返す文字列は実装依存です。IE は、場合によっては HTML/SGML として不正な文字列すら返します。

Firefox、Opera、Safari は、内部的には空白を捨てていません。空白のみのテキストノードが存在します。なので、自分でシリアライザ(DOM → HTML)を作れば何とかなります。

IE も、IXMLDOMDocument::preserveWhiteSpace プロパティを true にした上で XHTML を読み込ませれば、空白を保持できます。その上で、xml プロパティを見るか、やはり自分でシリアライザを作るか、どちらかになるでしょう。

# DOM → XML へシリアライズするときに、「空白を保持するか」「属性値を正規化するか」「デフォルト値を出力するか」「エラーが生じた場合どうするか」などのオプションが考えられます。その詳細は DOM3 Load&Save で規定されていますが、LSSerializer のマトモな実装は未だ皆無です。

2   名前: 匿名 : 2007/05/22(火) 20:31  ID:OF72WdCi sub-Cz
ああ、もう一つ。DOM ツリー修正後の HTML ソースではなく、単純にオリジナルのソースで良ければ、XMLHttpRequest で読み込んだ後、responseText を見れば OK。

3   名前: yoro : 2007/05/22(火) 20:31  ID:ECDmC1Px sub-1h
匿名さん、早速のご教授ありがとうございます。

私のおぼろげながら感じていた疑問とその原因や要因を明示していただき
スッキリしました。

これら情報を元にトライしてみます。

とりあえずこのスレッドは解決とさせて頂きます。

4   名前: 匿名 : 2007/05/22(火) 20:31  ID:oi1X0x1i sub-Cz
一応捕捉。

・Firefox、Opera、Safari は (new XMLSerializer).serializeToString(node) で、どんな場合でも(ノードが HTMLElement ではなく、innerHTML を持っていなくとも)シリアライズできます。

・ごくごく簡単なシリアライザは、以下のように書けます。遅いし、空要素の処理もしていませんが。
function serializer (node) {
    switch (node.nodeType) {
    case 1 : // Node.ELEMENT_NODE
        return String.prototype.concat.call (
            '<', node.tagName, serializeAttributes (node), '>',
              serializeChildNodes (node),
            '<\/', node.tagName, '>'
        );
    case 2 : // Node.ATTRIBUTE_NODE
        return String.prototype.concat.call (node.name, '="', node.value, '"');
    case 3 : // Node.TEXT_NODE
        return node.data;
        
    /*  以下、ノードタイプに応じた書式で出力
     *  ...
     */
     
    default :
        return '';
    }
}

function serializeAttributes (node) {
    var result = [ ], nodes = node.attributes;
    for (var i = 0, I = nodes.length; i < I; i++)
        if (nodes[i].specified) result.push (' ', serialize (nodes[i]));
    return result.join ('');
}

function serializeChildNodes (node) {
    var result = [ ], nodes = node.childNodes;
    for (var i = 0, I = nodes.length; i < I; i++)
        result.push (serialize (nodes[i]));
    return result.join ('');
}

・もう少し考慮すれば、各ノードのプロパティには、XML では文脈上許されない文字がありえます。特に、利用者にデータ入力させた場合など、出力時(入力時ではない)に以下のチェックを行わねばなりません。

要素:
・要素名が名前文字列であるかチェック。
・空要素の処理(NET 処理)。

属性:
・属性名が名前文字列であるかチェック。
・属性値内の「<」「&」「'」「"」をエスケープ。

テキスト:
・データ内の「<」「&」「]]>」をエスケープ。

CDATA セクション:
・データ内の「]]>」をエスケープ。

処理命令:
・ターゲット名が名前文字列であり、かつ「/xml/i」以外であるかチェック。
・データ内の「?>」をエスケープ。

コメント:
・データ内の「--」、データ末尾の「-」をエスケープ。

文書型宣言:
・ルート要素の名前と一致しているかチェック。
・外部識別子が適切な文字列であるかどうか。

これでもまだまだ不十分ではあるのですが、一応。

一覧へ戻る