なぜかCSSが読み込まれる

JEditorPaneでhtmlファイルを読み込んだ場合、ヘッダに書かれたスタイルシートは反映されません。 デフォルトのスタイルシートが使用されます。 こちらで用意したスタイルシートを適用するにはコードを書かなければなりません。 例えば次のようなコードだとスタイルシートは読み込まれないはずです。

// CssTest.java
import java.io.File;
import javax.swing.*;

public class CssTest extends JFrame
{
    public static final String TEST_HTML = "jeditorpane_test.html";
    
    public CssTest()
    {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        try
        {
            JEditorPane editorPane = new JEditorPane();
            editorPane.setEditable(false);
            editorPane.setContentType("text/html");
            editorPane.setPage(new File(TEST_HTML).toURI().toURL() );
            
            JScrollPane scrollPane = new JScrollPane(editorPane);
            getContentPane().add(scrollPane);
        }
        catch(Exception exc)
        {
            exc.printStackTrace();
        }
    }
    
    public static void main(String[] args)
    {
        CssTest app = new CssTest();
        app.setSize(640, 480);
        app.setVisible(true);
    }
}

しかし、読み込むhtmlファイルの内容によってはヘッダに書かれたスタイルシートが反映されます。 例えばxhtmlのファイルを読み込んだ場合は反映されます。 ただし正しく表示できるわけでは有りません。 JEditorPaneがhtml3.2にしか対応していないのでそれ以降の要素はもちろん表示できないのですが、それだけではないのです。 1行目のxml宣言にはスタイルが適用されず、そのまま表示されてしまいます。 正確には先頭の山カッコを除いた「?xml version="1.0" ... ?>」の部分が表示されます。

HTMLDocumentの構造を調べてみると、本来のツリー構造の外側にhtmlタグ、headタグとbodyタグが加えられているのがわかります。 2重になっているのです。 内側の部分、つまりxhtmlファイルの内容にだけスタイルが適用されているのがわかります。

xhtmlファイルだけがその様になるわけではありません。 例えば、html3.2のファイルの1行目に山カッコ閉じ「>」だけを挿入すると同様の結果になります。

>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
    <head>
        <link rel="stylesheet" href="cssファイル名" type="text/css">
        ... ヘッダの内容
    </head>
    <body>
        ... ドキュメントの内容
    </body>
</html>

パーサーが解釈できない記述があるとヘッダなどを補完しているように思えます。 xhtmlの例はxml宣言が解釈できなかったのではないでしょうか。

1行目のゴミを表示させないようにするにはどうしたらよいのでしょう? 答えは簡単で、htmlファイルの内容全てをheadタグで囲めば可能です。 これでjavaのコードにスタイルシートを読むコードを書かなくてもスタイルの適用をすることができます。

<head>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    <html>
        <head>
            <link rel="stylesheet" href="cssファイル名" type="text/css">
            ... ヘッダの内容
        </head>
        <body>
            ... ドキュメントの内容
        </body>
    </html>
</head>

もちろん、これはスタイルを読み込む正しい方法ではないので「ふぅん」と思うくらいにしておきましょう。 間違っても学校の課題や納品するソースに書いてはいけません。