2012-10-02 56 views
5

我正在嘗試使用Groovy和Java的ScriptEngine API來解析XML。 下面的代碼確實如此,但我想知道是否有更好的方法來做同樣的事情。還有,如果有任何與此相關的性能影響?通過Groovy在Java中進行XML解析

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; 
    } 
} 

輸出:

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

thankx很多羅布! – Arham

回答

6

你的Groovy腳本可能是「常規兒」 ...

這做同樣的事:

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

事實上,你可以使用GroovyShell而不是JVM腳本引擎,噸讓你到:

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

太棒了...謝謝蒂姆。 – Arham

+0

@Arham增加了另一種使用GroovyShell的方法:-) –

+0

感謝Tim,看到如此多的解決問題的方式非常棒,並且具有最小的冗長度。我添加了另一個使用ScriptEngine的更高性能的方式。 – Arham

4

爲了使ScritpEngine更好的性能,我們可以用可編譯接口。下面的代碼是來自Tim的評論和討論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; 
} 

輸出:

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