JTree: Как добавить атрибуты узлов в качестве собственных листьев?

Я визуализирую файлы XML с помощью javax.swing.JTree. Используя код из этого и это вопрос, я застрял на добавлении атрибутов из ноды как листьев к ней.

Этот простой XML:

<?xml version="1.0" encoding="utf-8"?>
<!-- comment -->
<MYXML xmlns="">
    <Header id=""></Header>
    <Product id="" name="">
        <Description>Some text</Description>
        <Ref id=""></Ref>
        <Data id="">
            <Ref id=""></Ref>
        </Data>
        <Form id=""></Form>
    </Product>
</MYXML>

анализируется до org.w3c.dom.Document и передается как org.w3c.dom.Node для рекурсивного построения JTree:

private DefaultMutableTreeNode buildTreeNode(Node rootNode) {
    DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(
            rootNode.getNodeName());
    NodeList children = rootNode.getChildNodes();

    for (int i = 0; i < children.getLength(); i++) {
        Node node = children.item(i);
        short nodeType = node.getNodeType();

        if (nodeType == Node.ELEMENT_NODE) {
            treeNode.add(buildTreeNode(node));

            // FIXME attributes should be leaves of their nodes
            if (node.hasAttributes()) {
                NamedNodeMap attributes = node.getAttributes();
                for (int j = 0; j < attributes.getLength(); j++) {
                    Node attr = attributes.item(j);
                    treeNode.add(new DefaultMutableTreeNode("@" + attr));
                }
            }
        } else if (nodeType == Node.TEXT_NODE) {
            String text = node.getTextContent().trim();
            if (!text.equals("")) {
                treeNode.add(new DefaultMutableTreeNode(text));
            }
        } else if (nodeType == Node.COMMENT_NODE) {
            String comment = node.getNodeValue().trim();
            treeNode.add(new DefaultMutableTreeNode("#" + comment));
        }
    }
    return treeNode;
}

Результат не тот, что я хотел:

результат

Листья «Заголовок», «Ссылка» и «Форма» должны быть узлами, а все атрибуты (отмеченные @) должны быть листьями своих узлов. Как я могу добиться этого с помощью моего рекурсивного подхода?

Вот мой рабочий пример на Gist.

EDIT: я понял это и ответил на свой вопрос ниже.


person rypel    schedule 22.05.2015    source источник
comment
Возможно, больше похоже на это?   -  person trashgod    schedule 23.05.2015


Ответы (2)


В TreeNode есть метод isLeaf, вам нужно его реализовать, потому что обычно он возвращает true, когда у этого узла нет детей (childrenCount==0), и false в противном случае. Вы хотите пометить элементы узла независимо от количества их дочерних элементов, поэтому вам необходимо реализовать/переопределить этот метод, чтобы он возвращал то, что вам нужно.

Также есть проблема в вашем алгоритме:

Вам нужно проверить, есть ли у вашего узла дочерние узлы или это только конечный узел с листьями. Вам нужно различать эти два и реализовывать правильную логику для обработки этого, вам решать, как вы интерпретируете этот xml в своем коде.

person Krzysztof Cichocki    schedule 22.05.2015
comment
Спасибо, это сделало работу. Это работало без вызова isLeaf(), так как логика основана на узлах документа (я должен был назвать rootNode до docNode, чтобы было понятно). - person rypel; 24.05.2015

Ну, наконец-то я разобрался, благодаря подсказкам Кшиштофа. Теперь узлы с дочерними элементами обрабатываются правильно, а листья атрибутов находятся там, где они должны быть:

private DefaultMutableTreeNode buildTreeNode(Node rootNode) {
    DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(
            rootNode.getNodeName());

    if (rootNode.hasAttributes()) {
        NamedNodeMap attributes = rootNode.getAttributes();

        for (int j = 0; j < attributes.getLength(); j++) {
            String attr = attributes.item(j).toString();
            treeNode.add(new DefaultMutableTreeNode("@" + attr));
        }
    }

    if (rootNode.hasChildNodes()) {
        NodeList children = rootNode.getChildNodes();

        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            short nodeType = node.getNodeType();

            if (nodeType == Node.ELEMENT_NODE)
                treeNode.add(buildTreeNode(node));

            else if (nodeType == Node.TEXT_NODE) {
                String text = node.getTextContent().trim();
                if (!text.equals(""))
                    treeNode.add(new DefaultMutableTreeNode(text));

            } else if (nodeType == Node.COMMENT_NODE) {
                String comment = node.getNodeValue().trim();
                treeNode.add(new DefaultMutableTreeNode("#" + comment));
            }
        }
    }
    return treeNode;

Что производит то, что я хотел:

введите здесь описание изображения

Для завершения исправленный пример на Gist.

person rypel    schedule 24.05.2015