JAXB - 解组XML异常

时间:2011-12-13 12:47:53

标签: java xml jaxb

我试过读一个大的xml文件(类似于500MB)。 首先,我使用xjc和我的XML的XSD文件。所有类都按预期生成。 试图读取文件我遇到了这个错误:javax.xml.bind.UnmarshalException:意外的元素。

这是我的代码:

(...)

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堆空间问题)并且不用标签读取标签获取相应的值,一个缓慢的猴子代码(不是行星的崛起的猴子)猿猴)。 :P

非常感谢。

2 个答案:

答案 0 :(得分: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...
}

答案 1 :(得分: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人提交)。