2011-12-13 95 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可用的上下文数量有关,以便它能够做出有关该做什么的决定。 (从好的一面来看,你不再需要明确的演员,因为你知道你得到了什么。) –