Menu

Tree [b12f85] master /
 History

HTTPS access


File Date Author Commit
 src 2014-06-20 teknopaul teknopaul [2f0920] First published version to github
 .gitignore 2014-06-20 teknopaul teknopaul [a7725a] Initial commit
 LICENSE 2014-06-20 teknopaul teknopaul [a7725a] Initial commit
 README.md 2014-06-20 teknopaul teknopaul [b12f85] fix more typos
 lgpl-3.0.txt 2014-06-20 teknopaul teknopaul [2f0920] First published version to github
 pom.xml 2014-06-20 teknopaul teknopaul [2f0920] First published version to github
 todo.text 2014-06-20 teknopaul teknopaul [2f0920] First published version to github

Read Me

Generation-X

Programatic XML generation without templates.

Using the Java org.w3c.dom APIs to create XML docs involves a lot of boiler plate code.

This project implements an XPath like syntax for generating new XML elements.

The following xGenPath will create the expected XML output.

/html/body/div#container/table.table/tbody/tr[5]

This is useful for generating XML when a templating system is not a good fit.

Install

mvn install

Example

This example code creates a bootstrap HTML page. Generation-X is perhaps better suited to genreating
XML but the HTML schema should be familiar so it should be easy to see from this example what
the intention of the code is.
N.B. select() is using XPaths and create() is useing xGenPaths.

XGen xGen = XGenFactory.newInstance();
xGen.setOutputMethod("html");

xGen.newDocument("/html{lang=en}/head/title").setTextContent(TITLE);

xGen.select("//head").create("link{rel=stylesheet}")
    .setAttribute("type", "text/css")
    .setAttribute("href", "http://maxcdn.bootstrapcdn.com/bootswatch/3.1.1/slate/bootstrap.min.css");

// Container
XGenNodeList container = xGen.select("//html").create("body/div.container");

// Header
container.create("div.row/div.col-md-12/h1.well").setTextContent(TITLE);

// Menu
container.create("div.row/div.col-md-2/ul.well/li[4]").setTextContent("Menu");

// jumbotron
xGen.select("//div[@class='row'][2]").create("div.col-md-10 jumbotron/h1").setTextContent("Programatic XML Generation");

// small footer
container.create("div.row/div.text-center/footer/p.small").setTextContent("Copyleft teknopaul");

// simplified XML serialization
xGen.serialize(new FileOutputStream("./src/test/eg/index.html"));

The above example uses only Generation-X code but behind the scenes the standard Java w3c Dom is used, you can
mix and match between the APIs.

// Create doc with w3c APIs
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = doc.createElement("wrapper");
doc.appendChild(root);

// Add a few elements with xGen
NodeList nl = XGenFactory.newInstance(doc).create(root, "data/fs/files/file[5]");

// Carry on with w3c
for( int i = 0 ; i < nl.getLength(); i++) {
    nl.item(i).setTextContent(getFile(i));
}

// Print with xGen
XGenFactory.newInstance(doc).serialize(System.out);

// Or print with Java APIs
DOMSource domSource = new DOMSource(doc);
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute("indent-number", "2");
Transformer serializer = factory.newTransformer();
if (serializer.getClass().getName().contains("org.apache")) {
    serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
}
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.transform(domSource, new StreamResult(System.out));

XGenNodeList

The XGen select() and create() methods return a w3c compatible NodeList but the object returned has some handy features.

XGenNodeList mutators

XGenNodeList has mutator methods that affect all the elements in the list.

xGenNodeList.setTextContent("foo")

will add "foo" to all the elements in the list. This is similar to jQuery code where all selectors are potentially arrays.

setTextContent() takes a var-args so if you know you have three elements you can write

xGen.create("/div/ul/li[3]").setTextContent("one", "two", "three");

setAttribute(name, value) also works on all the elements in the list.

as does appendChild() and also select() and create().

Chaining calls

XGenNodeList methods generally return this so you can chain calls

XGen xGen = XGenFactory.newInstance();
xGen.newDocument("/xml")
    .create("div/ul/li[3]")
    .setTextContent("foo")
    .setAttribute("abc", "123")
    .create("a/span")
    .setAttribute("class", "grey");
xGen.serialize(System.out);

Lambdas

For JDK 7 we dont have lambdas yet but there is an each() method to whet your appetite.

xGen.newDocument("/xml")
    .create("div/ul/li[3]")
    .each(new NodeMutator() {
        public void each(Node node) {
            ((Element)node).setAttribute("abc", "123");
            return node;
       }
    }); // you can chain more calls here

Dependencies

None at runtime, JUnit during the build.
Jar is only a few K at this stage

Licence

LGPL

Coming Soon...

Ideas for future development

  • Lamda support - need specific Java 8 builds.
  • xGenPath for jQuery - would be cool should be easy to port from Java.
  • xGenPath for nodejs - XML is not favoured in the nodejs community but might help someone.
  • xGenPath for JSON - Should be as useful for generating big JSON blobs as it is for XML.
  • Support for .. parent paths - This would save some xpath lookups, but might be hard to implement.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.