2012-10-02 16 views
5

Sto cercando di analizzare un XML utilizzando Groovy e l'API ScriptEngine di Java. Il codice sotto fa esattamente questo, ma volevo sapere se ci sono modi migliori per fare lo stesso. E anche se ci sono implicazioni sulla performance legate a questo?Analisi XML in Java tramite Groovy

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

import javax.script.Invocable; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 
/* 
<books> 
    <book id="1"> 
     <name>"Catcher In the Rye"</name> 
     <author>J.D. Salinger</author> 
    </book> 
    <book id="2"> 
     <name>"KiteRunner"</name> 
     <author>Khaled Hosseini</author> 
    </book> 
</books> 
*/ 

public class XMLParsing{ 
    public static void main(String[] args) { 
    Map<String, ArrayList<String>> resultMap 
            = new HashMap<String, ArrayList<String>>(); 
    resultMap = getBookDetails("c:\\temp\\book.xml"); 
    System.out.println(resultMap); 
    } 


    public static Map<String ArrayList<String>> getBookDetails(String scriptXml) { 
    Map<String, ArrayList<String>> resultMap = 
             new HashMap<String, ArrayList<String>>(); 
    ScriptEngineManager factory = new ScriptEngineManager(); 
    ScriptEngine engine = factory.getEngineByName("groovy"); 
    String fact = "import java.util.HashMap;" 
       + "import java.util.ArrayList;" 
       + "def getBookInformation(n){" 
       + "def map1 = new HashMap();" 
       + "xmlDesc = new XmlSlurper().parse(n);" 
       + "xmlDesc.book.findAll{it}.each {" 
       + "def list1 = new ArrayList();" 
       + "def id = [email protected];" 
       + 
       //"println id;"+ 
        "def name = it.name;" 
       + "def author = it.author;" 
       + "list1.add(name);" 
       + "list1.add(author);" 
       + "map1.put(id, list1);" 
       + "};" 
       + "return map1;}"; 
    try { 
     engine.eval(fact); 
     Invocable inv = (Invocable) engine; 
     Object[] params = {scriptXml};   
     resultMap = (Map<String,ArrayList<String>>) 
        inv.invokeFunction("getBookInformation", params); 
    } catch (ScriptException e) { 
     e.printStackTrace(); 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
    } 
    return resultMap; 
    } 
} 

uscita:

{1=["Catcher In the Rye", J.D. Salinger], 2=["KiteRunner", Khaled Hosseini]} 
+1

grazie mille Rob! – Arham

risposta

6

Lo script Groovy potrebbe essere "groovy-er" ...

Questo fa la stessa cosa:

String fact = "def getBookInformation(n) {" + 
       " xmlDesc = new XmlSlurper().parse(n)\n" + 
       " xmlDesc.book.findAll().collectEntries {\n"+ 
       " [ ([email protected]):[ it.name, it.author ] ]\n" + 
       " }\n" + 
       "}" ; 

In effetti, è possibile utilizzare il GroovyShell anziché il motore di script JVM e t ridurti a:

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 { [ ([email protected]):[ it.name, it.author ] ] }") ; 
    return (Map<String, ArrayList<String>>)ret ; 
    } 
} 
+0

fantastico ... grazie Tim. – Arham

+0

@Arham Aggiunto un altro modo di farlo con GroovyShell :-) –

+0

Grazie a Tim, è davvero bello vedere così tanti sapori di risolvere un problema con verbosità minima. Ho aggiunto un altro modo più performante di usare ScriptEngine. – Arham

4

Al fine di rendere più performante ScritpEngine, potremmo usare l'interfaccia compilabile. Il codice seguente è un mix di novità dai commenti di Tim e dalla discussione 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 { [ ([email protected]):[ it.name, it.author ] ] }");   
      return (Map<String, ArrayList<String>>)(script.eval()); 
     } 
    } catch (ScriptException e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

uscita:

{1=["Catcher In the Rye", J.D. Salinger], 2=["KiteRunner", Khaled Hosseini]}