我有一段时间没有使用 JAXB,但是无论选择什么解决方案,您都需要遍历 XML 文档来读取数据,隐式使用 DOM(然后可能是 XPath)或显式使用 SaX 之类的流 API(推送模型,通过回调获取数据)或StAX(拉模型,通过调用方法获取数据)。
JAXB Users Guide 在“4.4. 处理大型文档”小节“4.4.1. 按块处理文档”中提供了以下信息。我在 Github 上添加了示例的链接。我这里没有空间来包含所有内容。
这种XML适合块处理;主要思想是使用 StAX API,运行一个循环,并分别解组各个块。您的程序作用于单个块,然后将其丢弃。这样,您最多只能在内存中保留一个块,从而可以处理大型文档。
有关如何执行此操作的更多信息,请参阅 JAXB RI 分发中的 streaming-unmarshalling example 和 partial-unmarshalling example。流式解组示例的优点是它可以处理任意嵌套级别的块,但它需要您处理推送模型 --- JAXB 解组器会将新块“推送”给您,您需要正确处理它们在那里。
相比之下,部分解组示例在拉模型中工作(这通常使处理更容易),但这种方法在数据绑定部分而不是重复部分有一些限制。
pull-parser 和 xml-channel 的例子看起来也很有希望。我根据pull-parser 中的简单代码制作了一个 MWE。该实现位于Eclipse Implementation of JAXB。
$ cat source.xml
<?xml version="1.0" encoding="UTF-8" ?>
<Example id="10" date="1970-01-01" version="1.0">
<Properties>properties</Properties>
<Summary>summary</Summary>
<Document id="1">one</Document>
<Document id="2">two</Document>
<Document id="3">three</Document>
</Example>
$ cat document.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Document">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:int"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
$ cat Main.java
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Unmarshaller;
import java.io.FileReader;
import javax.xml.stream.*;
import static javax.xml.stream.XMLStreamConstants.*;
import generated.Document;
public class Main {
public static void main(String[] args) throws Exception {
int id = 3;
JAXBContext jaxbContext = JAXBContext.newInstance("generated");
Unmarshaller um = jaxbContext.createUnmarshaller();
XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLStreamReader xmlr = xmlif.createXMLStreamReader(new FileReader("source.xml"));
int event;
while (true) {
event = xmlr.next();
if (event == END_DOCUMENT) break;
if (event == START_ELEMENT && xmlr.getName().getLocalPart().equals("Document") && xmlr.getAttributeValue(null, "id").equals("3")) {
Document document = (Document) um.unmarshal(xmlr);
System.out.printf("Text is \"%s\"\n", document.getValue());
}
}
}
}
$ java --version
openjdk 15.0.1 2020-10-20
OpenJDK Runtime Environment (build 15.0.1+9-18)
OpenJDK 64-Bit Server VM (build 15.0.1+9-18, mixed mode, sharing)
$ wget https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.0/jaxb-ri-3.0.0.zip
$ unzip jaxb-ri-3.0.0.zip
$ export PATH=`pwd`/jaxb-ri/bin:$PATH
$ export CLASSPATH=.:jaxb-ri/mod/*
$ xjc.sh document.xsd
Java major version: 15
parsing a schema...
compiling a schema...
generated/Document.java
generated/ObjectFactory.java
$ javac generated/*.java
$ javac Main.java
$ java Main
Text is "three"