2011-12-13 66 views
2

我試圖讀取一個大的XML文件(像500MB)。 首先,我使用xjc和我的XML的XSD文件。所有類都按預期生成。 試圖讀取文件我有這個錯誤:javax.xml.bind.UnmarshalException:意外的元素。JAXB - 解組XML異常

這裏是我的代碼:

(...)

JAXBContext context = JAXBContext.newInstance("br.com.mypackage"); 
Unmarshaller unmarshaller = context.createUnmarshaller(); 
File f = new File("src/files/MyHuge.CNX"); 
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
InputStream in = new FileInputStream(f); 
XMLEventReader eventReader = inputFactory.createXMLEventReader(in); 
Person p = null; 
int count = 0; 
while (eventReader.hasNext()) { 
    XMLEvent event = eventReader.nextEvent(); 
    if (event.isStartElement()) { 
     StartElement startElement = event.asStartElement(); 
     if (startElement.getName().getLocalPart() == ("person")) { 
     p = (Person) unmarshaller.unmarshal(eventReader); 
     } 
    } 
} 

的問題是在解組操作。

Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"identification"). Expected elements are <{}messageAll> 

我使用這個鏈接作爲例子,使我自己的代碼:JAXB - unmarshal OutOfMemory: Java Heap Space

有人有線索辦呢?我現在想要的只是讀取一個巨大的XML文件,而不用解組XML(java堆空間問題)的外部對象,也不需要通過標記獲取相應的值來讀取標記,慢速和猴子代碼(不是Planet of the Planet的猴子的人猿)。 :P

非常感謝。

+0

u能共享XML和這裏使用的類及其JAXB映射?是否在包'br.com.mypackage'中有一個包含註釋'@XmlRootElement(namespace =「」,name =「identification」)'的類' –

+0

Arun,在Person類中有這樣的註解: '@XmlAccessorType (XmlAccessType.FIELD)' '@XmlType(name =「」,propOrder = {「identification」,「address」,「whatever」})' 所以,我認爲XJC會做所有與小事有關的事情註釋。也許這是XSD文件上的問題? –

+0

您可以在將它傳遞給解組器之前嘗試打印事件閱讀器的內容嗎?它看起來像不是將'person'元素傳遞給傳遞'identification'元素的根。而'Person'類應該有@XmlType(name =「person」,propOrder = {「identification」,「address」,「whatever」})'。你還可以提供識別對象的類型嗎? –

回答

1

我解決了這個問題,此代碼波紋管:

public List<Person> testeUnmarshal() { 
    List<Person> people = new ArrayList<Person>(); 
    Person p = null; 
    try { 
    JAXBContext context = JAXBContext.newInstance(Person.class); 
    Unmarshaller unmarshaller = context.createUnmarshaller(); 
    File f = new File(FILE_PATH); 
    XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
    XMLEventReader eventReader = inputFactory.createXMLEventReader(new FileInputStream(f)); 
    while (eventReader.hasNext()) { 
     XMLEvent event = eventReader.peek(); 
     if (event.isStartElement()) { 
     StartElement start = event.asStartElement(); 
    if (start.getName().getLocalPart() == "person")) { 
      JAXBElement<Person> jax_b = unmarshaller.unmarshal(eventReader, Person.class); 
     p = jax_b.getValue(); 
    } 
     } 
     eventReader.next(); 
    } 
    } catch (Exception e) { 
    } 
    return persons; 
} 

我能控制內存中使用計數的對象數量(對於數據庫中的1000人提交)。

1

我猜測,問題是你已經從事件流消耗的<person>所以JAXB不知道它在做什麼;它需要那個元素在那裏,因此它可以建立對象。因此,我懷疑你需要偷看流,以決定是否消費(和丟棄)或解組:

while (eventReader.hasNext()) { 
    XMLEvent event = eventReader.peek(); 
    if (event.isStartElement()) { 
     StartElement startElement = event.asStartElement(); 
     if (startElement.getName().getLocalPart() == ("person")) { 
     p = (Person) unmarshaller.unmarshal(eventReader); 
     continue; // Assume you've done something with p; go round loop again 
     } 
    } 
    eventReader.nextElement(); // Discard... 
} 
+0

我試過了。事實上,我發佈了我的代碼摘要。我正在爲while循環的每次迭代獲取下一個元素。無論如何,我用peek方法進行測試(如你所做的那樣),但它不起作用。 我想避免使用「切換方式」獲取每個字段及其值的代碼。你能給我一個好的教程鏈接嗎?也許我不明白解組函數的目的,如果出席我的需要。 –

+0

大家好,問題解決了。這裏是鏈接到該溶液中: http://pastebin.com/JQ6uN9Te '如果(start.getName()getLocalPart()== 「人」)){ 的JAXBElement jax_benef =的Unmarshaller.unmarshal (eventReader,Person.class); p = jax_benef.getValue(); }' 我不知道爲什麼舊的方法不工作(解組使用Person對象,而不是JAXBElement)。你有關於它不工作的線索嗎? –

+0

@TSoares:我不知道,但我想它必須與JAXB可用的上下文數量有關,以便它能夠做出有關該做什麼的決定。 (從好的一面來看,你不再需要明確的演員,因爲你知道你得到了什麼。) –