JEditorPaneHTMLEditorKitParserGraph图结构处理

wen java案例 3

本文目录导读:

JEditorPaneHTMLEditorKitParserGraph图结构处理

  1. 场景一:提取 HTML 中嵌入的图形源代码(如 SVG 或 LaTeX)
  2. 场景二:将 HTML DOM 结构转换为图(树形或关系图)
  3. 场景三:处理 HTML 中的“流程图”标签(Mermaid、PlantUML、Graphviz DOT)
  4. 场景四:HTMLEditorKit 解析器本身的图结构(内部状态机)
  5. 最重要的建议:放弃 JEditorPane 处理复杂图

这是一个非常技术性的问题,你提到的 JEditorPaneHTMLEditorKitParserGraph 组合在一起,通常指向两个主要方向:

  1. 解析 HTML 并提取其中的图形结构(如 SVG、Canvas、表格布局、流程图)。
  2. 解析 HTML DOM 树本身作为一个图结构(树形图)。

由于“JEditorPane + HTMLEditorKit”这一组合在 Java Swing 中已经非常古老且功能有限(对 CSS2/3、现代 JS、SVG 支持极差),处理“图”结构时通常需要绕过其自带的渲染器,直接操作底层数据。

以下根据你最可能的业务场景,给出几种“图”处理方案:


提取 HTML 中嵌入的图形源代码(如 SVG 或 LaTeX)

问题: 你希望 JEditorPane 显示 HTML,同时能识别并导出其中的 <svg><img> 标签构成的图。

解决方案: 使用 HTMLEditorKit.ParserCallback 解析 HTML 流,捕获特定标签。

核心代码片段(提取 SVG 节点):

import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;
public class GraphExtractor extends HTMLEditorKit.ParserCallback {
    private StringBuilder svgContent = new StringBuilder();
    private boolean inSVG = false;
    @Override
    public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
        if (t == HTML.Tag.SVG) { // 注意:JEditorPane 的内置解析器可能不支持 SVG 标签
            inSVG = true;
            svgContent.append("<svg");
            // 提取属性
            Enumeration<?> names = a.getAttributeNames();
            while (names.hasMoreElements()) {
                Object key = names.nextElement();
                if (!key.equals(HTML.Attribute.IMPLIED)) {
                    svgContent.append(" ").append(key).append("=\"").append(a.getAttribute(key)).append("\"");
                }
            }
            svgContent.append(">");
        }
        // 其他标签处理(如 <div class="graph">)
    }
    @Override
    public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
        if (inSVG && t == HTML.Tag.IMG) {
            // 忽略自闭合元素内的 img
        }
    }
    @Override
    public void handleText(char[] data, int pos) {
        if (inSVG) {
            svgContent.append(data);
        }
    }
    @Override
    public void handleEndTag(HTML.Tag t, int pos) {
        if (t == HTML.Tag.SVG) {
            inSVG = false;
            svgContent.append("</svg>");
        }
    }
    public String getExtractedGraph() {
        return svgContent.toString();
    }
    // 使用方式
    public static void main(String[] args) throws Exception {
        String html = "<html><body><svg width='100' height='100'><circle cx='50' cy='50' r='40'/></svg></body></html>";
        HTMLEditorKit kit = new HTMLEditorKit();
        MyParserCallback callback = new MyParserCallback();
        kit.parse(new StringReader(html), callback, true);
        System.out.println(callback.getExtractedGraph());
    }
}

将 HTML DOM 结构转换为图(树形或关系图)

问题: 你想根据 HTML 的层级结构(如嵌套 <div><ul>/<li>)生成一个树状图或流程图。

解决方案: JEditorPane 内部会构建一个 HTMLDocument,其结构实际上是 Element 树,你可以遍历这个树,构建你自己的图数据结构(JGraphT 的 Graph 对象)。

实现步骤:

  1. 加载 HTML 到 JEditorPane

    JEditorPane editorPane = new JEditorPane();
    editorPane.setContentType("text/html");
    editorPane.setText(htmlContent); // 或者 page()
    editorPane.setEditable(false);
  2. 从 Document 中提取结构

    HTMLDocument doc = (HTMLDocument) editorPane.getDocument();
    Element root = doc.getDefaultRootElement();
    // 使用递归构建图(示例:转换为邻接表)
    Map<Element, List<Element>> graph = new HashMap<>();
    buildGraph(root, graph);
  3. 递归构建函数

    private void buildGraph(Element parent, Map<Element, List<Element>> graph) {
        List<Element> childrenList = new ArrayList<>();
        graph.put(parent, childrenList);
        for (int i = 0; i < parent.getElementCount(); i++) {
            Element child = parent.getElement(i);
            childrenList.add(child);
            buildGraph(child, graph);
        }
    }
  4. 可视化(可选):将 graph 传给 JGraphX、JUNG 或 GraphStream 进行渲染。


处理 HTML 中的“流程图”标签(Mermaid、PlantUML、Graphviz DOT)

问题: HTML 中包含 <div class="mermaid"><pre> 代码块,里面是流程图描述语言。

解决方案: JEditorPane 无法直接渲染 Mermaid/PlantUML,你必须:

  1. 使用 ParserCallback 找到这些标签。
  2. 提取内部的文本内容(如 graph TD; A-->B)。
  3. 调用外部渲染器(如 PlantUML jar、Graphviz 命令行、或 Mermaid 的 JS 引擎通过 Java JS 桥)。
  4. 将渲染输出的图片(PNG/SVG)替换到 JEditorPane 中(通过插入 HTML.Tag.IMG 或者设置 Icon)。

HTMLEditorKit 解析器本身的图结构(内部状态机)

问题: 你想理解 JEditorPane 背后的 HTML 解析器(sun.net.www.parser.HTMLEditorKit$Parserjavax.swing.text.html.parser.DocumentParser)的语法图。

解决方案: 查看源码,Swing 的内部解析器基于 DTD(文档类型定义)驱动,它使用 DTD 类(这是一个图结构)来判断标签的合法父子关系,如果要修改或调试解析行为,你可能需要:

  • 继承 HTMLEditorKit 并覆盖 getParser() 方法。
  • 使用自定义的 DTD 实例。
  • 或者完全放弃内置解析器,改用 Jsoup(建议)。

最重要的建议:放弃 JEditorPane 处理复杂图

需求 推荐方案
静态 HTML 显示 JEditorPane + HTMLEditorKit (足够)
解析 DOM 结构 Jsoup (解析快、API清晰、支持选择器)
渲染现代图 (SVG/Canvas) JavaFX WebView (内嵌 Chromium,完美支持)
显示特定流程图 (Mermaid/PlantUML) JavaFX WebView + Mermaid CDN
生成自定义图 (节点和边) JGraphXGraphStream (纯 Java 绘图)

如果你确实想用 JEditorPane 处理图,请明确具体是哪一种图:

  • A. 完全用 HTML 画出来的表格式图(如 ASCII art 或表格布局)?
  • B. <object> 标签嵌入的 SVG 图?
  • C. 纯文本描述(DOT 语言)?
  • D. DOM 树本身?

请补充说明,我可以给出更精确的代码示例。

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