Saturday, June 8, 2013

XML pretty-printing and XSLT processing in Rhino JavaScript

One of my favourite utilities on Linux is xmllint, in particular xmllint --format. Ugly, unreadable XML in, nice and pretty XML out. Unfortunately, xmllint is not usually installed on Windows. Oh, I could just download the Windows executable. Or, I could write my own little XML pretty printer in JavaScript (Mozilla Rhino bundled with the JDK). Well, the advantage of this approach, is that it can be used on any platform where the JDK is installed, even when you are not allowed to compile or install other software.
xmlToString = function(doc) {
   var domreg = org.w3c.dom.bootstrap.DOMImplementationRegistry.newInstance();
   var ls = domreg.getDOMImplementation("LS");
   var w = ls.createLSSerializer();
   w.getDomConfig().setParameter("format-pretty-print", true);
   var lsout = ls.createLSOutput();
   var out = new java.io.StringWriter();
   lsout.setCharacterStream(out);
   w.write(doc, lsout);
   out.close();
   return "" + out.toString();
};

try {
   var inp = new java.io.File(arguments[0]);
   var dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
   dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
   dbf.setNamespaceAware(true);
   var db = dbf.newDocumentBuilder();
   var doc = db.parse(inp);
   println(xmlToString(doc));
} catch (e) {
  if (e.javaException)
    e.javaException.printStackTrace();
  throw e;
}
Another tool I often use is xsltproc, for applying XSLT stylesheets. Here is a JavaScript equivalent for that:
xmlToString = function(doc) {
   var domreg = org.w3c.dom.bootstrap.DOMImplementationRegistry.newInstance();
   var ls = domreg.getDOMImplementation("LS");
   var w = ls.createLSSerializer();
   w.getDomConfig().setParameter("format-pretty-print", true);
   var lsout = ls.createLSOutput();
   var out = new java.io.StringWriter();
   lsout.setCharacterStream(out);
   w.write(doc, lsout);
   out.close();
   return "" + out.toString();
};

getDocBuilder = function() {
   var dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
   dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
   dbf.setNamespaceAware(true);
   return dbf.newDocumentBuilder();
};

loadXMLFile = function(file) {
   var inp = new java.io.File(file);
   return getDocBuilder().parse(inp);
};

applyXSLT = function(doc, xslt) {
   var dsDoc = new javax.xml.transform.dom.DOMSource(doc);
   var dsXSLT = new javax.xml.transform.dom  .DOMSource(xslt);
   var tf = javax.xml.transform.TransformerFactory.newInstance();
   var xf = tf.newTransformer(dsXSLT);
   var out = getDocBuilder().newDocument();
   var drOut = new javax.xml.transform.dom.DOMResult(out);
   xf.transform(dsDoc, drOut);
   return out;
};

try {
   var doc = loadXMLFile(arguments[0]);
   var xslt = loadXMLFile(arguments[1]);
   var out = applyXSLT(doc, xslt);
   println(xmlToString(out));
} catch (e) {
   if (e.javaException)
      e.javaException.printStackTrace();
   throw e;
}

No comments:

Post a Comment