本文目录导读:

这个错误信息看起来是 Java Swing 中 JEditorPane 和 HTMLEditorKit 解析 HTML 时遇到的一个问题。“非法选择器” 通常指的是 HTML 解析器遇到了无法识别的或格式错误的 CSS 选择器。
根本原因
JEditorPane 和 HTMLEditorKit 使用的是过时且不完整的 HTML 3.2 / 4.0 解析器(带有有限的 CSS 支持),当你尝试加载包含现代 CSS 或非标准选择器的 HTML 内容时,解析器可能会抛出 IllegalSelector 错误。
常见触发场景
- 使用了现代 CSS 选择器(如
nth-child,last-of-type,:before,:after等)。 - 复杂的或非标准的 CSS 类/ID 命名(例如包含特殊字符、数字开头、CSS 保留关键字)。
- HTML 中嵌入了
<style>,且内容包含 Java 解析器不认识的选择器语法。 - 使用了自定义的
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 Saucer(
xhtmlrenderer),它对 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
快速排查步骤
- 打印出 HTML:检查传递给
setText() 或 read() 的 HTML 字符串中是否有任何 CSS 选择器。
- 测试简化版:将 HTML 简化为
<html><body><p>test</p></body></html>,看是否还会报错。
- 检查自定义 EditorKit:如果你继承了
HTMLEditorKit 并重写了 getParser() 方法,检查你的自定义解析器实现。
这个错误的核心是 JEditorPane 的 CSS 解析能力太弱。最直接的解决方案是移除非标准 CSS(尤其是伪类/伪元素/属性选择器),或者考虑使用更现代的 HTML 渲染方案。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
如果是为了渲染简单文本,直接移除所有 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 Saucer(
xhtmlrenderer),它对 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
快速排查步骤
- 打印出 HTML:检查传递给
setText()或read()的 HTML 字符串中是否有任何 CSS 选择器。 - 测试简化版:将 HTML 简化为
<html><body><p>test</p></body></html>,看是否还会报错。 - 检查自定义 EditorKit:如果你继承了
HTMLEditorKit并重写了getParser()方法,检查你的自定义解析器实现。
这个错误的核心是 JEditorPane 的 CSS 解析能力太弱。最直接的解决方案是移除非标准 CSS(尤其是伪类/伪元素/属性选择器),或者考虑使用更现代的 HTML 渲染方案。