【问题标题】:JAXB - unmarshal XML exceptionJAXB - 解组 XML 异常
【发布时间】:2011-12-13 12:47:53
【问题描述】:

我试图读取一个大的 xml 文件(大约 500MB)。 首先,我将 xjc 与我的 XML 的 XSD 文件一起使用。所有类都按预期生成。 尝试读取文件时出现此错误:javax.xml.bind.UnmarshalException: unexpected element.

这是我的代码:

(...)

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

非常感谢。

【问题讨论】:

  • 你能分享这里使用的 xml 和类以及它们的 jaxb 映射吗?包br.com.mypackage中是否有注解@XmlRootElement(namespace="", name = "identification")的类
  • Arun,在 Person 类上,有这个注解:@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"identification","address","whatever"}) 所以,我认为 XJC 会做所有与注解相关的小事。可能是 XSD 文件的问题?
  • 您能在将事件阅读器的内容传递给解组器之前尝试打印它吗?看起来不是在根处传递 person 元素,而是在传递 identification 元素。而Person 类应该有@XmlType(name = "person", propOrder = {"identification","address","whatever"})。能否也给出识别对象的类型。
  • 我做了一个测试。我试图“解组”标识对象。它不起作用。它启动相同的异常: 引起:javax.xml.bind.UnmarshalException:意外元素(uri:“”,本地:“标识”)。预期元素是 我编辑了删除人员的 XML 文件。我只留下了 5 个人。有了这个小文件,我成功地使用 XJC 生成的最外部对象进行了解组操作。所有 5 个人都按预期创建。通过这个测试,我认为这不是注释问题。 (我怎样才能把 xsd 文件发给你?)

标签: java xml jaxb


【解决方案1】:

我猜问题是您已经从事件流中使用了&lt;person&gt;,所以 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...
}

【讨论】:

  • 我试过了。事实上,我发布了我的代码摘要。我正在为 while 循环的每次迭代获取下一个元素。无论如何,我用 peek 方法进行了测试(就像你所做的那样),但它不起作用。我想避免使用“切换方式”来获取每个字段及其值的代码。你能给我一个好的教程的链接吗?也许我不了解解组功能的目的以及是否满足我的需要。
  • 大家好,问题已解决。这是解决方案的链接:pastebin.com/JQ6uN9Teif (start.getName().getLocalPart() == "person")) { JAXBElement&lt;Person&gt; jax_benef = unmarshaller.unmarshal(eventReader, Person.class); p = jax_benef.getValue(); } 我不知道为什么旧方法不起作用(解组使用 Person 对象而不是 JAXBElement)。你知道它没有工作吗?
  • @TSoares:我不知道,但我想它必须与 JAXB 可用的上下文量有关,以便它决定要做什么。 (从好的方面来说,你不再需要明确的演员表,因为你知道你得到了什么。)
【解决方案2】:

我用下面的代码解决了这个问题:

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 人)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    相关资源
    最近更新 更多