I\'m trying to parse an XML using Groovy and the ScriptEngine API of Java. The code below does exactly that but I wanted to know if there are any better ways of doing the sa
Your Groovy script could be "groovy-er"...
This does the same thing:
String fact = "def getBookInformation(n) {" +
" xmlDesc = new XmlSlurper().parse(n)\n" +
" xmlDesc.book.findAll().collectEntries {\n"+
" [ (it.@id):[ it.name, it.author ] ]\n" +
" }\n" +
"}" ;
Indeed, you could use the GroovyShell
rather than the JVM scripting engine, and that gets you down to:
import java.util.ArrayList;
import java.util.Map;
import groovy.lang.Binding ;
import groovy.lang.GroovyShell ;
public class XMLParsing {
public static void main(String[] args) {
Map<String, ArrayList<String>> resultMap = getBookDetails("test.xml");
System.out.println(resultMap);
}
public static Map<String, ArrayList<String>> getBookDetails( String scriptXml ) {
Binding b = new Binding() ;
b.setVariable( "xmlFile", scriptXml ) ;
GroovyShell shell = new GroovyShell( b ) ;
Object ret = shell.evaluate( "new XmlSlurper().parse( xmlFile ).book.findAll().collectEntries { [ (it.@id):[ it.name, it.author ] ] }" ) ;
return (Map<String, ArrayList<String>>)ret ;
}
}
In order to make ScritpEngine more performant, we could use Compilable interface. The code below is a mix of novelty from Tim's comments and the discussion here.
public static Map<String, ArrayList<String>> getBookDetails(String scriptXml) {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("groovy");
engine.put("xmlFile", scriptXml);
try {
if (engine instanceof Compilable) {
CompiledScript script = ((Compilable) engine).compile( "new XmlSlurper().parse( xmlFile ).book.findAll().collectEntries { [ (it.@id):[ it.name, it.author ] ] }" );
return (Map<String, ArrayList<String>>)(script.eval());
}
} catch (ScriptException e) {
e.printStackTrace();
}
return null;
}
Output:
{1=["Catcher In the Rye", J.D. Salinger], 2=["KiteRunner", Khaled Hosseini]}