Planet JFX

JavaFX XML Framework Jim Clarke Jim.Clarke@sun.com

As a part of my work with JavaFX Script, I noticed there are a number of basic frameworks that have yet to be developed. So, I decided to create frameworks for XML and JSON. This paper reflects the work I have completed thus far on an XML framework. I will follow this up with a paper on the JSON framework. Java Code Examples

The XML framework is checked into the openjfx-compiler project on java.net (https://openjfx-compiler.dev.java.net/) in the runtime section of the source in the javafx.xml package.

This document assumes the reader has familiarity with XML, Document Object Model, Xpath, and of course JavaFX Script. The examples provided here are in the openjfx-compiler syntax and this XML framework requires the OpenJFX Compiler. In deciding what should be in this framework, I relied on my previous experiences with Java XML, JavaScript and Groovy. At the basis of the framework is the Java Document Object Model, DOM, as it is readily available in modern JREs. Let's start by reading an XML document.



Reading XML[]

To read an XML stream, there is javafx.xml.DocumentBuilder. This class is an amalgamation of the features found in javax.xml.parsers.DocumentBuilderFactory and javax.xml.parsers.DocumentBuilder. There are settings, like namespaceAware, and validating, a method for creating a new empty Document, and various forms for parsing XML data streams into fully populated Documents.

First, an instance of javafx.xml.DocumentBuilder is obtained, setting the appropriate properties. Then this instance can be used to parse the xml stream, returning a populated javafx.xml.Document instance that represents the DOM tree. In this example, the XML is read from a URI connection. There are also parsers to read from files, other java.io streams, and String attributes.

 import javafx.xml.*;
 
 var builder = DocumentBuilder{
 		namespaceAware:true
         	validating:true
 		ignoringComments:false
 		};
 var document =
               builder.parseURI(“http://code.google.com/apis/kml/documentation/KML_Samples.kml”));
 System.out.println(document);

Running this produces the familiar XML output:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <kml xmlns="http://earth.google.com/kml/2.2">
   <Document>
     <name>KML Samples</name>
     <open>1</open>
     <description>Unleash your creativity with the help of these examples!</description>
     <Style id="downArrowIcon">
       <IconStyle>
         <Icon>
           <href>http://maps.google.com/mapfiles/kml/pal4/icon28.png</href>
         </Icon>
       </IconStyle>
     </Style>
     <Style id="globeIcon">
       <IconStyle>
         <Icon>
           <href>http://maps.google.com/mapfiles/kml/pal3/icon19.png</href>
         </Icon>
       </IconStyle>
 ...
 ...
 ...

Fetching Document Elements[]

The javafx.xml.Document class provides two ways to fetch elements and nodes from within the DOM tree. First, there is the DOM getElementsByTagName and its companion method getElementsByTagNameNS that provides namespace support. The getElementsByTagName functions return sequences of javafx.xml.Element objects.

By Tag[]

In this example, all the elements with the name “Icon” within the Google sample XML file are returned. Because this is a sequence, all JavaFX sequence features can be applied to the returned list.

 var elem = document.getElementsByTagName("Icon");
 System.out.println("ICON size = {sizeof elem}");

Produces:

 ICON size = 12

Xpath Query[]

The second method employs the javax.xml.xpath framework for executing xpath queries against the document object model.To find nodes within the DOM tree, any valid XPATH query can be evaluated with the matching javafx.xml.Node's returned. For documents, the document itself is the root node for the query.

var nodes = document.query("//kml/Document/Folder/Placemark/name/text()");
System.out.println("PlaceMark size = {sizeof nodes}");
for(i in nodes) {
   System.out.println("{i.value}");
}

Produces:

 PlaceMark size = 100
 Simple placemark
 Floating placemark
 Extruded placemark
 Descriptive HTML
 Tessellated
 Untessellated
 Absolute
 Absolute Extruded
 Relative
 Relative Extruded


Xpath queries can also be submitted on individual nodes and in this case the node becomes the root node for the query. Nodes use the same xpath query function and syntax as the Document.

Creating new XML Documents[]

To create a new, empty document, use the builder.createDocument() function. This returns a Document instance.

 var document = builder.createDocument();
 document.standalone = false;

To add a root node to the document, use the Document.createElement function, then assign it to the documentElement attribute of the Document.

 var topElement = document.createElement("top");
 document.documentElement = topElement;
 System.out.println(document);

Produces:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <top/>

To change the name of the element, just assign a new value to the name attribute of the Element.

 document.documentElement.name = "foo";
 System.out.println(document);

Produces:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <foo/>


Adding Elements and Nodes[]

To add attributes to an element, use the Element.addAttribute function

document.documentElement.addAttribute("name", "visit www.grandtricks.wap.sh");

Produces:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <foo name="jim" />

To add an element to another element, just use the Element.addElement function. Similarly, add text and comments to elements using their respective functions.

var barElem = document.documentElement.addElement("bar");
 barElem.addText("Now is the time that tries men's souls");
 barElem.addComment("This is a comment");
 System.out.println(document);

Produces:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <foo name="jim">
   <bar>Now is the time that tries men's souls<!--This is a comment--></bar>
 </foo>

Building an entire document at once[]

The real beauty of it all comes when you use JavaFX Script Object Literals to build the entire tree at once.

document.documentElement.children = [ 
   Element {
       name:"one"
       document: document
       children: [ 
           Element { 
               name: 'a1' 
               document: document
               children: [
                   Text{value:"Yash", document: document}
               ]
               attributes: [
                   Attribute{name:"name", value:"yash", document: document}
               ]
           },
           Element { name: 'b1', document: document },
           Element { name: 'c1', document: document }
       ]
       },
   Element {
       name:"two"
       document: document
       children: [ 
           Element { name: 'a1', document: document},
           Element { name: 'b1', document: document },
           Element { name: 'c1', document: document }        
       ]
   }
 ];
 System.out.println(document);

Produces:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <foo name="jim">
   <one>
     <a1 name="joe">yash</a1>
     <b1/>
     <c1/>
   </one>
   <two>
     <a1/>
     <b1/>
     <c1/>
   </two>
 </foo>

TODO's[]

Some of the lessons and take-aways from this first go around are this:

  • First, for this last example, I would like to restructure the initialization of the framework objects so that certain attributes can be inherited from the node's parent. Thus, you would not have to include the redundant “document” attribute in each Object Literal within the tree.
  • Second, standard XML formatting in the JDK is very basic. I would like to implement a good pretty print XML formatter.
  • Third, I am sure there are more efficient ways to do parts of this and I would welcome any recommendations.
  • Next, there are some obscure DOM features that I have not yet implemented, features like entity resolver and error handlers.
  • Lastly, I am sure there are features that should be included in this framework that I have not thought of and some better ways to leverage JavaFX script. So I welcome any suggestions.

Summary[]

This just provides a simple overview for this framework and there are many more features yet to be explored. Please look a the documentation in the source files and soon there should be some JavaDoc style documentation. The next major step is to start creating demos to integrate this and the upcoming JSON framework into cool JavaFX Script applications. If you have questions, comments, suggestions, or complaints, send me email at [emailto:jim.clarke@sun.com].

References:[]

Extensible Markup Language (XML) 1.0 (Fourth Edition), W3C, [1] Document Object Model (DOM), W3C, [2] XML Path Language (Xpath) Version 1.0, W3C, [3] JavaTM 2 Platform Standard Edition 5.0 API Specification, Sun Microsystems, Inc. , [4] The OpenJFX Compiler Project, java.net, [https://openjfx-compiler.dev.java.net/ ]