XML Viewer in Java

XML Viewer in Java

This example shows the XML document in the form of a tree.

---------------- XMLView.java ------------------

import java.io.*;
import java.util.*;
import java.nio.file.*;

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.beans.property.*;

import javax.xml.parsers.*;
import org.w3c.dom.*;

public class XMLView extends Application {
  Label label;
  TreeTableView<org.w3c.dom.Node> treeTableView;

  @Override
  public void start(Stage stage) {
    List<String> p = getParameters().getRaw();
    File file;
    if (!p.isEmpty()) {
      file = new File(p.get(0));
      if (!file.isFile()) throw new RuntimeException(file.getName() + " file not found");
    } else {
      file = new File("sample.xml");
      if (!file.exists()) createDemo(file);
    }
    label = new Label();
    treeTableView = createTreeTableView(file);
    BorderPane layout = new BorderPane();
    layout.setCenter(treeTableView);
    layout.setBottom(label);
    stage.setScene(new Scene(layout, 600, 400));
    stage.show();
  }

  TreeTableView<org.w3c.dom.Node> createTreeTableView(File file) {
    TreeTableView<org.w3c.dom.Node> treeTableView = new TreeTableView<>(createTreeItems(file));
    treeTableView.setShowRoot(true);
    treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
    TreeTableColumn<org.w3c.dom.Node, TreeItem<org.w3c.dom.Node>> nameColumn = new TreeTableColumn<>("Name");

    nameColumn.setCellValueFactory(
      (TreeTableColumn.CellDataFeatures<org.w3c.dom.Node, TreeItem<org.w3c.dom.Node>> cellData) ->
        new ReadOnlyObjectWrapper<TreeItem<org.w3c.dom.Node>>(cellData.getValue())
    );

    Image[] images = new Image[tagNames.length];
    try {
      Image image = new Image(getClass().getResourceAsStream("image.png"));
      for(int i = 0; i < images.length; i++) {
        images[i] = new WritableImage(image.getPixelReader(), i * 16, 0, 16, 16);
      }
    } catch (Exception e) {}

    nameColumn.setCellFactory(column -> {
      TreeTableCell<org.w3c.dom.Node, TreeItem<org.w3c.dom.Node>> cell = new TreeTableCell<org.w3c.dom.Node, TreeItem<org.w3c.dom.Node>>() {
        ImageView[] imageView = new ImageView[images.length];
        { for(int i = 0; i < imageView.length; i++) imageView[i] = new ImageView(images[i]); }

        @Override
        protected void updateItem(TreeItem<org.w3c.dom.Node> item, boolean empty) {
          super.updateItem(item, empty);
          if (item != null && !empty) {
            org.w3c.dom.Node node = item.getValue();
            if (item.getValue() != null) {
              String s = node.getNodeName();
              setText(s == null ? "" : s.trim());
              setGraphic(imageView[typeIndex(node.getNodeType())]);
              return;
            }
          }
          setText(null);
          setGraphic(null);
        }
      };
      return cell;
    });

    nameColumn.setPrefWidth(300);
    nameColumn.setSortable(false);
    treeTableView.getColumns().add(nameColumn);

    TreeTableColumn<org.w3c.dom.Node, String> valueColumn = new TreeTableColumn<>("Value");
    valueColumn.setCellValueFactory(cellData -> {
      TreeItem<org.w3c.dom.Node> item = cellData.getValue();
      org.w3c.dom.Node childNode = item.getValue();
      if (childNode != null) {
        String s = childNode.getNodeType() == org.w3c.dom.Node.DOCUMENT_TYPE_NODE ?
          ((DocumentType)childNode).getInternalSubset() : childNode.getNodeValue();
        if (s != null) {
          return new ReadOnlyObjectWrapper<String>(s.trim());
          //return new ReadOnlyObjectWrapper<String>(s.trim().replaceAll("\\s+", " "));
        }
      }
      return null;
    });

    valueColumn.setPrefWidth(100);
    valueColumn.setSortable(false);
    treeTableView.getColumns().add(valueColumn);

    treeTableView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
      if (newValue != null) {
        org.w3c.dom.Node node = newValue.getValue();
        if (node != null) {
          label.setText(tagNames[typeIndex(node.getNodeType())]);
          return;
        }
      }
      label.setText("");
    });
    treeTableView.getSelectionModel().selectFirst();
    return treeTableView;
  }

  TreeItem<org.w3c.dom.Node> createTreeItems(File file) {
    TreeItem<org.w3c.dom.Node> root = null;
    try {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      Document doc = builder.parse(file);
      doc.getDocumentElement().normalize();
      root = new TreeItem<>(doc);
      root.setExpanded(true);
      addChildrenItem(root);
    } catch (Exception e) { e.printStackTrace(); }
    return root;
  }

  void addChildrenItem(TreeItem<org.w3c.dom.Node> root) {
    org.w3c.dom.Node node = root.getValue();
    if (node.hasAttributes()) {
      NamedNodeMap attrs = node.getAttributes();  
      for(int i = 0; i < attrs.getLength(); i++) {
        root.getChildren().add(new TreeItem<org.w3c.dom.Node>(attrs.item(i)));
      }
    }
    NodeList list = node.getChildNodes(); 
    for (int i = 0; i < list.getLength(); i++) { 
      org.w3c.dom.Node childNode = list.item(i);
      if (childNode != null && (childNode.getNodeType() != org.w3c.dom.Node.TEXT_NODE ||
        (childNode.getNodeValue() != null && childNode.getNodeValue().trim().length() > 0))) {
        TreeItem<org.w3c.dom.Node> treeItem = new TreeItem<>(childNode);
        treeItem.setExpanded(true);
        root.getChildren().add(treeItem);
        addChildrenItem(treeItem);
      }
    } 
  } 

  final String tagNames[] = {"Not considered", "Element", "Attribute",
    "Text", "CDATA section", "Processing Instruction",
    "Comment", "Document", "Document Type"};

  int typeIndex(int t) {
    switch (t) {
      case org.w3c.dom.Node.ELEMENT_NODE:                return 1;
      case org.w3c.dom.Node.ATTRIBUTE_NODE:              return 2;
      case org.w3c.dom.Node.TEXT_NODE:                   return 3;
      case org.w3c.dom.Node.CDATA_SECTION_NODE:          return 4;
      case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE: return 5;
      case org.w3c.dom.Node.COMMENT_NODE:                return 6;
      case org.w3c.dom.Node.DOCUMENT_NODE:               return 7;
      case org.w3c.dom.Node.DOCUMENT_TYPE_NODE:          return 8;
    }
    return 0;
  }

  void createDemo(File file) {
    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"1.0\"?>\n");
    sb.append(" <!DOCTYPE DocType [<!ENTITY name \"Value\">]>\n");
    sb.append(" <?Target Instruction?>\n");
    sb.append(" <!--Comment-->\n");
    sb.append("<Element Attribute=\"Attribute\">\n");
    sb.append(" <Element>\n");
    sb.append("  Text &name;\n");
    sb.append(" </Element>\n");
    sb.append(" <![CDATA[CDATA Section]]>\n");
    sb.append(" <EmptyElement/>\n");
    sb.append("</Element>\n");
    try {
      Files.write(file.toPath(), sb.toString().getBytes());
    } catch (Exception e) { }
  }
}

Download ZIP

Back