本文目录导读:

- 核心原理:HTMLEditorKit.Parser 与 Callback
- 最短路径代码示例(提取纯文本)
- 为什么说这是“最短路径”?
- 进阶:“最短路径” 提取结构化数据(如所有链接)
- 注意事项(也是最短路径的代价)
您提到的 JEditorPane、HTMLEditorKit、Parser 和 “最短路径” 这几个关键词组合在一起,通常指向一个特定的技术问题场景:
如何通过自定义 HTMLEditorKit 的 Parser(解析器 / 回调),以最短路径(最简代码 / 最直接的方法)从 Swing 的 JEditorPane 中提取纯文本或结构化内容,而不是渲染它。
就是利用 Swing 的 HTML 解析能力来 “解析” 而非 “显示”。
核心原理:HTMLEditorKit.Parser 与 Callback
JEditorPane 默认使用 HTMLEditorKit 来渲染 HTML。HTMLEditorKit 内部有一个 Parser 接口(实现类通常是 javax.swing.text.html.parser.ParserDelegator)。
要 “最短路径” 地获取解析结果,关键不是去操作 JEditorPane 的文档树,而是重写 ParserCallback,让解析器在遇到标签、文本、注释时直接回调你的逻辑。
[JEditorPane] --> [HTMLEditorKit] --> [Parser] --解析--> [ParserCallback(你)]
最短路径代码示例(提取纯文本)
这个例子里,我们不走 JEditorPane 的 Document 模型,而是直接用一个 StringReader 把 HTML 喂给解析器,然后通过回调把文本收集起来,这就是 “最短路径” 的做法 —— 省掉了构建 DOM 树、遍历的步骤。
import javax.swing.text.html.parser.ParserDelegator;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.MutableAttributeSet;
import java.io.StringReader;
public class HtmlToTextExtractor {
public static String extractText(String html) {
StringBuilder result = new StringBuilder();
// 定义回调:只关心文本(handleText)和换行(handleStartTag br/p 等)
HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback() {
@Override
public void handleText(char[] data, int pos) {
result.append(data); // 提取纯文本
}
@Override
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
// 简单处理换行标签,让输出更像纯文本
if (t == HTML.Tag.BR || t == HTML.Tag.P || t == HTML.Tag.DIV) {
result.append("\n");
}
}
@Override
public void handleEndTag(HTML.Tag t, int pos) {
if (t == HTML.Tag.P || t == HTML.Tag.DIV) {
result.append("\n");
}
}
@Override
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
if (t == HTML.Tag.BR) {
result.append("\n");
}
}
// 忽略评论、错误、结束标签等
};
try {
// 使用 ParserDelegator 解析字符串
ParserDelegator parser = new ParserDelegator();
parser.parse(new StringReader(html), callback, true); // true = ignore charset
} catch (Exception e) {
e.printStackTrace();
}
return result.toString().trim();
}
// 测试
public static void main(String[] args) {
String html = "<html><body><h1>Hello</h1><p>World</p><br/><b>Bold</b></body></html>";
System.out.println(extractText(html));
// 输出:
// Hello
// World
// Bold
}
}
为什么说这是“最短路径”?
- 没有 JEditorPane 实例化:不需要创建
JEditorPane、不需要设置ContentType、不需要等它渲染。 - 没有 Document 遍历:不需要
getDocument().getRootElements()再递归。 - 直接调用 Parser:
ParserDelegator是轻量级的,直接解析字符串。 - 简洁的回调:只重写需要的方法(
handleText,handleStartTag),忽略其他干扰。
进阶:“最短路径” 提取结构化数据(如所有链接)
同样的模式,只需在回调里拦截 <a> 标签的 href 属性。
public static List<String> extractLinks(String html) {
List<String> links = new ArrayList<>();
HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback() {
@Override
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
if (t == HTML.Tag.A) {
Object href = a.getAttribute(HTML.Attribute.HREF);
if (href != null) {
links.add(href.toString());
}
}
}
// 其他方法留空
};
// ... 解析同上
return links;
}
注意事项(也是最短路径的代价)
- 非严格解析:
ParserDelegator是 Swing 的简单 HTML 3.2 解析器,对现代 HTML5、CSS、JavaScript 支持很差,遇到复杂页面可能会解析失败或丢失内容。 - 性能:对于大段 HTML,这种逐字符回调 + 字符串拼接可能不是最快的,但绝大多数场景下够用。
- 编码:示例中用了
true忽略字符集检测,HTML 包含charset声明,且与系统默认不同,需要自己处理Charset转换。
“JEditorPane HTMLEditorKit Parser 最短路径” = 直接用 ParserDelegator + ParserCallback 解析 HTML 字符串。
- 优势:代码极短、无需 Swing 组件、专注于解析数据。
- 劣势:解析能力有限(仅适合简单 HTML 提取),不适合渲染或复杂 DOM 操作。
如果你的需求是 “从 HTML 里最快、最简单取点文本或属性”,这就是最短路径,如果需要更强大的 HTML 解析(比如处理复杂嵌套、CSS 选择器),请转用 Jsoup,那才是真正的“捷径”。