2012-10-02 25 views
5

Estoy tratando de analizar un XML usando Groovy y la API ScriptEngine de Java. El siguiente código hace exactamente eso, pero quería saber si hay otras formas mejores de hacer lo mismo. ¿Y también si hay implicaciones de rendimiento relacionadas con esto?Análisis XML en Java a través de 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; 
    } 
} 

Salida:

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

gracias Rob mucho! – Arham

Respuesta

6

Su guión maravilloso podría ser "groovy-er" ...

Esto hace lo mismo:

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

De hecho, podría usar el GroovyShell en lugar del motor de scripts JVM, y t lo lleva 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

increíble ... gracias Tim. – Arham

+0

@Arham Agregó otra forma de hacerlo con GroovyShell :-) –

+0

Gracias Tim, es realmente genial ver tantos sabores de resolver un problema con mínima verbosidad. He agregado otra forma más eficaz de usar ScriptEngine. – Arham

4

Con el fin de hacer ScritpEngine con más prestaciones, podríamos usar interfaz compilable. El siguiente código es una mezcla de novedad de los comentarios de Tim y la discusión 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; 
} 

Salida:

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