JEditorPaneHTMLEditorKitParserError错误处理

wen java案例 78

本文目录导读:

JEditorPaneHTMLEditorKitParserError错误处理

  1. 捕获并处理解析异常
  2. 自定义 HTMLEditorKit 的错误处理
  3. 预处理 HTML 以修复常见错误
  4. 使用更健壮的解析器(如 JSoup)预处理
  5. 设置全局错误监听(高级)

针对 JEditorPane 和 HTMLEditorKit 在解析 HTML 时出现的 ParserError(解析器错误),通常是因为遇到了格式不规范的 HTML 或标签未正确关闭等问题,Swing 默认的 HTML 解析器(基于 Swing 自己的简易解析器,而非浏览器的完整解析器)对 HTML 的容错性较差,遇到错误可能会静默跳过或抛出异常。

以下是几种常见的错误处理及解决方案:


捕获并处理解析异常

使用 try-catch 包裹设置文本的操作:

import javax.swing.*;
import javax.swing.text.html.*;
import java.io.*;
public class HTMLErrorHandler {
    public static void main(String[] args) {
        JEditorPane editorPane = new JEditorPane();
        editorPane.setContentType("text/html");
        editorPane.setEditable(false);
        // 可能包含错误 HTML 的字符串
        String badHtml = "<html><body><p>Test<b>No close</p></html>";
        try {
            editorPane.setText(badHtml);
        } catch (Exception e) {
            System.err.println("HTML 解析错误: " + e.getMessage());
            // 可执行降级策略,如显示纯文本
            editorPane.setText(badHtml.replaceAll("<[^>]*>", ""));
        }
    }
}

自定义 HTMLEditorKit 的错误处理

通过继承 HTMLEditorKit 并覆盖 getParserCallback() 或使用 ParserDelegator 的 setErrorHandler 来捕获具体的解析错误。

示例:设置错误处理器

import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
import javax.swing.text.*;
public class CustomHTMLEditorKit extends HTMLEditorKit {
    @Override
    public ViewFactory getViewFactory() {
        return new HTMLFactory() {
            @Override
            public View create(Element elem) {
                return super.create(elem);
            }
        };
    }
    @Override
    public Document createDefaultDocument() {
        HTMLDocument doc = (HTMLDocument) super.createDefaultDocument();
        // 设置解析器
        ParserDelegator parser = new ParserDelegator() {
            @Override
            public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
                super.parse(r, new ErrorHandlingCallback(cb), ignoreCharSet);
            }
        };
        // 通过反射或其他方式设置解析器
        // 更推荐的方式:使用文档的 setParser 方法(需强制转换)
        return doc;
    }
    // 内部回调类,包裹原始回调并捕获错误
    private static class ErrorHandlingCallback extends HTMLEditorKit.ParserCallback {
        private final HTMLEditorKit.ParserCallback delegate;
        public ErrorHandlingCallback(HTMLEditorKit.ParserCallback delegate) {
            this.delegate = delegate;
        }
        @Override
        public void handleError(String errorMsg, int pos) {
            System.err.println("解析错误 at position " + pos + ": " + errorMsg);
            // 可选择忽略,继续解析
        }
        // 其他回调方法直接委托
        @Override
        public void handleText(char[] data, int pos) {
            delegate.handleText(data, pos);
        }
        @Override
        public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
            delegate.handleStartTag(t, a, pos);
        }
        @Override
        public void handleEndTag(HTML.Tag t, int pos) {
            delegate.handleEndTag(t, pos);
        }
        @Override
        public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
            delegate.handleSimpleTag(t, a, pos);
        }
        @Override
        public void handleComment(char[] data, int pos) {
            delegate.handleComment(data, pos);
        }
        @Override
        public void handleEndOfLineString(String eol) {
            delegate.handleEndOfLineString(eol);
        }
    }
}
// 使用时:
JEditorPane editor = new JEditorPane();
editor.setEditorKit(new CustomHTMLEditorKit());
editor.setText("<html><body><p>Test<b>No close</p></html>");

预处理 HTML 以修复常见错误

在传给 JEditorPane 之前,使用简单规则清理 HTML:

public static String sanitizeHtml(String html) {
    if (html == null) return "";
    // 关闭常见的未闭合标签
    html = html.replaceAll("<br>", "<br/>");
    html = html.replaceAll("<img([^>]*)>", "<img$1/>");
    // 确保 img 等自闭合标签正确
    // 移除不合法的属性或标签(根据需要)
    return html;
}
// 使用:
String cleanHtml = sanitizeHtml(badHtml);
editorPane.setText(cleanHtml);

使用更健壮的解析器(如 JSoup)预处理

如果项目允许添加依赖,推荐使用 JSoup 清理 HTML:

import org.jsoup.Jsoup;
import org.jsoup.safety.Safelist;
public static String cleanWithJsoup(String dirtyHtml) {
    // 使用宽松的安全列表,保留大多数标签和属性
    String cleaned = Jsoup.clean(dirtyHtml, Safelist.relaxed());
    // 或者使用更精确的:Safelist.basic() / Safelist.simpleText()
    return cleaned;
}
// 
String safeHtml = cleanWithJsoup(badHtml);
editorPane.setText(safeHtml);

设置全局错误监听(高级)

通过重写 HTMLEditorKit.ParserCallback 的 handleError 方法,可以捕获所有解析错误,上面的 ErrorHandlingCallback 已经演示了这一点,你也可以直接在默认的 HTMLEditorKit 中使用:

HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument();
doc.setParser(new ParserDelegator() {
    @Override
    public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
        super.parse(r, new HTMLEditorKit.ParserCallback() {
            @Override
            public void handleError(String errorMsg, int pos) {
                System.err.println("Error: " + errorMsg + " at " + pos);
                // 可以继续向原始回调传递错误,或忽略
                if (cb != null) cb.handleError(errorMsg, pos);
            }
            // 其他方法委托给 cb
            // 注意:所有方法都需要重写并委托
        }, ignoreCharSet);
    }
});
editorPane.setDocument(doc);

方法 适用场景 复杂度
简单 try-catch 仅需基本容错 低
自定义 Kit + 错误回调 需要记录/跟踪具体解析错误 中
预处理 HTML(正则/Soup) 可控的输入源,可提前清理 中
更换解析器(JSoup 预处理) 项目允许依赖,需高质量清理 高(但效果好)

推荐做法:

  • HTML 来源不可控(如用户输入),先用 JSoup 清理,再传给 JEditorPane。
  • 如果必须使用 Swing 原生解析器,则实现 错误回调 捕获 handleError,避免静默失败。

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝