JEditorPaneHTMLEditorKitParserMethodIllegalSelector非法选择

wen java案例 2

本文目录导读:

JEditorPaneHTMLEditorKitParserMethodIllegalSelector非法选择

  1. 根本原因
  2. 常见触发场景
  3. 解决方案
  4. 示例:使用 Flying Saucer(更好的 CSS 支持)
  5. 快速排查步骤

这个错误信息看起来是 Java Swing 中 JEditorPaneHTMLEditorKit 解析 HTML 时遇到的一个问题。“非法选择器” 通常指的是 HTML 解析器遇到了无法识别的或格式错误的 CSS 选择器。

根本原因

JEditorPaneHTMLEditorKit 使用的是过时且不完整的 HTML 3.2 / 4.0 解析器(带有有限的 CSS 支持),当你尝试加载包含现代 CSS 或非标准选择器的 HTML 内容时,解析器可能会抛出 IllegalSelector 错误。

常见触发场景

  1. 使用了现代 CSS 选择器(如 nth-child, last-of-type, :before, :after 等)。
  2. 复杂的或非标准的 CSS 类/ID 命名(例如包含特殊字符、数字开头、CSS 保留关键字)。
  3. HTML 中嵌入了 <style>,且内容包含 Java 解析器不认识的选择器语法。
  4. 使用了自定义的 HTMLEditorKit,但扩展的解析方法中存在 bug。

解决方案

简化 CSS / 避免现代选择器

HTML 内容是你自己生成的,请确保只使用基本的选择器

  • 标签选择器body, p, div
  • 类选择器.classname(确保类名以字母开头,只包含字母、数字、连字符、下划线)
  • ID 选择器#idname
  • 后代选择器div p(简单的空格分隔)

避免使用

  • 伪类(hover, first-child
  • 伪元素(:before
  • 属性选择器([type="text"]
  • 组合器(>、、)

删除或注释掉 <style>

如果是为了渲染简单文本,直接移除所有 CSS 样式,或将其内联到元素的 style 属性中(<p style="color:red">)通常更安全。

捕获异常并降级处理

HTML 来源不可控(例如用户输入或外部网页),需要捕获异常,避免程序崩溃:

import javax.swing.*;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import java.io.StringReader;
public class SafeHtmlViewer {
    public static void main(String[] args) {
        JEditorPane editorPane = new JEditorPane();
        editorPane.setContentType("text/html");
        // 设置 a 自定义的 HTMLEditorKit 来捕获异常
        HTMLEditorKit kit = new HTMLEditorKit() {
            @Override
            public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException {
                try {
                    super.read(in, doc, pos);
                } catch (Exception e) {
                    // 记录错误,但不中断执行
                    System.err.println("HTML parse error: " + e.getMessage());
                    // 可选:尝试降级为纯文本
                }
            }
        };
        // 简化样式表(可选)
        StyleSheet styleSheet = new StyleSheet();
        styleSheet.addRule("p { margin: 0; }");
        kit.setStyleSheet(styleSheet);
        editorPane.setEditorKit(kit);
        // 示例:可能包含非法选择器的 HTML
        String unsafeHtml = "<html><body><p style='color:red'>Hello</p></body></html>";
        try {
            editorPane.read(new StringReader(unsafeHtml), "text/html");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

升级到现代 Swing 组件(推荐)

JEditorPane 的 HTML 渲染能力非常有限,如果项目对 HTML 展示有较高要求(现代 CSS、复杂布局),强烈建议:

  • 使用 JWebView(JavaFX):通过 javafx.scene.web.WebView 嵌入到 Swing 中(使用 JFXPanel)。
  • 使用第三方库:如 Flying Saucerxhtmlrenderer),它对 CSS 2.1 支持更好。
  • 使用纯文本或 JLabel只是简单富文本,考虑使用 JLabel 的 HTML 支持。

示例:使用 Flying Saucer(更好的 CSS 支持)

<!-- Maven 依赖 -->
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-core</artifactId>
    <version>9.9.0</version>
</dependency>
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xhtmlrenderer.resource.FSEntityResolver;
// 渲染 XHTML 到 BufferedImage 或直接输出到 Graphics2D

快速排查步骤

  1. 打印出 HTML:检查传递给 setText()read() 的 HTML 字符串中是否有任何 CSS 选择器。
  2. 测试简化版:将 HTML 简化为 <html><body><p>test</p></body></html>,看是否还会报错。
  3. 检查自定义 EditorKit:如果你继承了 HTMLEditorKit 并重写了 getParser() 方法,检查你的自定义解析器实现。

这个错误的核心是 JEditorPane 的 CSS 解析能力太弱。最直接的解决方案是移除非标准 CSS(尤其是伪类/伪元素/属性选择器),或者考虑使用更现代的 HTML 渲染方案。

抱歉,评论功能暂时关闭!