首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

手把手教你用 Java Swing 打造 XML 編輯器(一):XML 樹形展示與 XTree 核心組件

     編輯:Java 相關知識

為什麼選擇樹形結構展示 XML?

XML 本質是層次化數據:單一根元素、巢狀子元素、屬性附加。樹形視圖(JTree)天然匹配這種結構——根節點對應文檔根元素,分支對應子元素,葉子節點對應文本內容或屬性。用戶可直觀展開/摺疊、定位節點、理解文檔架構。

技術棧準備

  • JAXP (Java API for XML Processing):統一解析接口,支援 DOM/SAX/StAX。本文採用 DOM 模式,將整個文檔載入內存樹。
  • Xerces 解析器:Apache Xerces 是 JAXP 默認實現,含 xercesImpl.jar、xml-apis.jar,置於 Classpath。
  • Swing 組件:JTree、DefaultTreeModel、DefaultMutableTreeNode、JScrollPane、JFrame。

XTree 組件設計:繼承 JTree,封裝解析與建模

類結構

public class XTree extends JTree {
    // 域
    private DefaultMutableTreeNode treeNode; // 模型根節點
    private DocumentBuilderFactory dbf;      // JAXP 工廠
    private DocumentBuilder db;              // DOM 構建器
    private Document doc;                    // 解析後文檔對象

    // 構造器
    public XTree(String xmlText) throws ParserConfigurationException { ... }

    // 核心私有方法
    private Node parseXml(String text) { ... }           // 字符串 -> DOM Node
    private DefaultMutableTreeNode createTreeNode(Node) { ... } // DOM Node -> Swing 树節點 (遞歸)
    private String getNodeType(Node) { ... }             // 節點類型 -> 可讀字符串
}

關鍵實現細節

1. DOM 解析:字符串轉 Document

private Node parseXml(String text) {
    try {
        ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes("UTF-8"));
        doc = db.parse(bis);
        return doc.getDocumentElement(); // 返回根元素節點
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(0); // 簡化版直接退出,後續改進
    }
    return null;
}

2. 遞歸構建 Swing 树節點

private DefaultMutableTreeNode createTreeNode(Node domNode) {
    // 節點顯示文本:元素顯示標籤名,文本節點顯示內容
    String display = (domNode.getNodeType() == Node.TEXT_NODE) 
                     ? domNode.getNodeValue() 
                     : domNode.getNodeName();
    DefaultMutableTreeNode swingNode = new DefaultMutableTreeNode(display);

    // 處理屬性:作為子節點展示 [Attribute] name="value"
    NamedNodeMap attrs = domNode.getAttributes();
    if (attrs != null) {
        for (int i = 0; i < attrs.getLength(); i++) {
            Node attr = attrs.item(i);
            swingNode.add(new DefaultMutableTreeNode(
                "[Attribute] --> " + attr.getNodeName() + "=\"" + attr.getNodeValue() + "\""));
        }
    }

    // 遞歸處理子節點
    if (domNode.hasChildNodes()) {
        NodeList children = domNode.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);
            if (child.getNodeType() == Node.ELEMENT_NODE) {
                swingNode.add(createTreeNode(child)); // 元素節點遞歸
            } else if (child.getNodeType() == Node.TEXT_NODE) {
                String text = child.getNodeValue().trim();
                if (!text.isEmpty() && !text.equals("\n") && !text.equals("\r\n")) {
                    swingNode.add(createTreeNode(child)); // 非空白文本節點
                }
            }
        }
    }
    return swingNode;
}

3. 節點類型可讀化

private String getNodeType(Node node) {
    switch (node.getNodeType()) {
        case Node.ELEMENT_NODE: return "Element";
        case Node.ATTRIBUTE_NODE: return "Attribute";
        case Node.TEXT_NODE: return "Text";
        case Node.CDATA_SECTION_NODE: return "CDATA Section";
        case Node.COMMENT_NODE: return "Comment";
        case Node.DOCUMENT_NODE: return "Document";
        // ... 其他類型
        default: return "???";
    }
}

測試驅動類:XTreeTester

public class XTreeTester extends JFrame {
    private XTree xTree;
    private JScrollPane scrollPane;

    public XTreeTester(String title, String xml) throws ParserConfigurationException {
        super(title);
        setLayout(new BorderLayout());
        xTree = new XTree(xml);
        scrollPane = new JScrollPane(xTree);
        add(scrollPane, BorderLayout.CENTER);
        setSize(400, 300);
        centerOnScreen();
        setVisible(true);
    }
    // main 方法:讀取命令行指定 .xml 文件,傳入構造器
}

運行方式

java -cp .;xercesImpl.jar;xml-apis.jar XTreeTester sample.xml

代碼亮點與不足

亮點待改進
封裝性好:XTree 獨立可複用,測試類極簡異常處理粗暴 (System.exit)
遞歸算法清晰處理混合內容 (元素+文本+屬性)無編輯能力 (setEditable(false))
屬性節點獨立展示,語義明確無默認視圖,必須提供 XML 文件
採用標準 JAXP API,解析器可換裝大文檔 DOM 佔用記憶體高

下一步預告

第二篇將構建 雙分欄編輯器框架(JSplitPane 分割樹視圖與文本編輯區),增強 XTree:默認歡迎樹、優雅異常處理、公開刷新 API,為文件操作奠基。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved