July 29, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Displaying XML in a Swing JTree

  • March 3, 2008
  • By Rob Lybarger
  • Send Email »
  • More Articles »

Another minor thing to nail down relates to the nature of "pretty-printed" XML and the return value of a Node object's getChildNodes() method. (You might want to read my previous article that discusses this. The link is in the Overview section.) My design requirement is that I only want to show actual Element objects in the tree, not text nodes, comments, attributes, or other non-Element node types. To address this, a helper method is written to return a Vector of all the children of a given node that are specifically of the Element type:

private Vector<Element> getChildElements(Node node) {
   Vector<Element> elements = new Vector<Element>();
   NodeList list = node.getChildNodes();
   for (int i=0 ; i<list.getLength() ; i++) {
      if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
         elements.add( (Element) list.item(i));
      }
   }
   return elements;
}

You will see this method used in several of the implementation methods, which you can finally address. The first item of business is to keep track of the registered TreeModelListeners:

Vector<TreeModelListener> listeners =
   new Vector<TreeModelListener>();

public void addTreeModelListener(TreeModelListener listener) {
   if (!listeners.contains(listener)) {
      listeners.add(listener);
   }
}

public void removeTreeModelListener(TreeModelListener
   listener) {
   listeners.remove(listener);
}

For the next item, you need to provide the root node for the tree. This will be the root node of our document object, wrapped in the XMLTreeNode explained above:

public Object getRoot() {
   if (document==null) {
      return null;
   }
   Vector<Element> elements = getChildElements(document);
   if (elements.size() > 0) {
      return new XMLTreeNode( elements.get(0));
  }
   else {
      return null;
   }
}

Returning null is completely fine, and signals to the JTree object that there is nothing to be displayed. A quick safety check allows the JTree to function during initialization before the model is handed a Document to work with. (Failing to do this will generate NullPointerExceptions.)

Now that the tree has the root node, it will start asking for the number of child nodes under each node, and will ask for each of those child nodes in turn. The returned children objects will again be Element objects wrapped in an XMLTreeNode object.

public int getChildCount(Object parent) {
   if (parent instanceof XMLTreeNode) {
      Vector<Element> elements =
         getChildElements( ((XMLTreeNode)parent).getElement() );
      return elements.size();
   }
   return 0;
}

public Object getChild(Object parent, int index) {
   if (parent instanceof XMLTreeNode) {
      Vector<Element> elements =
         getChildElements( ((XMLTreeNode)parent).getElement() );
      return new XMLTreeNode( elements.get(index) );
   }
   else {
      return null;
   }
}

public int getIndexOfChild(Object parent, Object child) {
   if (parent instanceof XMLTreeNode &&
      child instanceof XMLTreeNode) {
      Element pElement = ((XMLTreeNode)parent).getElement();
      Element cElement = ((XMLTreeNode)child).getElement();
      if (cElement.getParentNode() != pElement) {
         return -1;
      }
      Vector<Element> elements = getChildElements(pElement);
       return elements.indexOf(cElement);
   }
   return -1;
}

Now, to inform the default table cell renderer which icon to draw for a given node, the follow method is consulted:

public boolean isLeaf(Object node) {
   if (node instanceof XMLTreeNode) {
      Element element = ((XMLTreeNode)node).getElement();
      Vector<Element> elements = getChildElements(element);
      return elements.size()==0;
   }
   else {
      return true;
   }
}




Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel