我需要解析潜在的大型XML文件,其中的模式已经在几个XSD文件中提供给我,所以XML绑定非常受欢迎。我想知道是否可以使用JAXB以块分析文件,如果是这样,如何。JAXB是否可以解析块中的大型XML文件
回答
这在user guide中有详细说明。从http://jaxb.java.net/下载的JAXB包含一个如何一次解析一个块的示例。
当文档是大的,这是 通常是因为有重复 部分在里面。也许这是一个购买 的订单,其中包含大量订单项, 或者它可能是一个包含 大量日志条目的XML日志文件。
这种XML适用于 块处理;主要思路是 分别使用StAX API,运行一个循环,并分别解组单个块 。您的程序将作用于单个块上的 ,然后将其丢弃。 通过这种方式,您将只保留 内存中最多的一个块,这允许您使用 来处理大型文档。
见流,解组 例子和部分解组 例如在JAXB RI分布 更多有关如何做到这一点。该 流,解组例如有 优点是,它可以在任意 窝水平处理块,但它需要 你对付推模式--- JAXB解组将“推”新 块给你,你”你需要 在那里处理它们。
相比之下,局部解组 例如工作在拉取模型(其通常 使处理更容易), 但这种方法有一些局限性 在其它数据绑定部分比 重复部分。
因为代码很重要,所以这里是一个PartialUnmarshaller
谁读大块文件成块。它可以使用这种方式new PartialUnmarshaller<YourClass>(stream, YourClass.class)
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.*;
import java.io.InputStream;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static javax.xml.stream.XMLStreamConstants.*;
public class PartialUnmarshaller<T> {
XMLStreamReader reader;
Class<T> clazz;
Unmarshaller unmarshaller;
public PartialUnmarshaller(InputStream stream, Class<T> clazz) throws XMLStreamException, FactoryConfigurationError, JAXBException {
this.clazz = clazz;
this.unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
this.reader = XMLInputFactory.newInstance().createXMLStreamReader(stream);
/* ignore headers */
skipElements(START_DOCUMENT, DTD);
/* ignore root element */
reader.nextTag();
/* if there's no tag, ignore root element's end */
skipElements(END_ELEMENT);
}
public T next() throws XMLStreamException, JAXBException {
if (!hasNext())
throw new NoSuchElementException();
T value = unmarshaller.unmarshal(reader, clazz).getValue();
skipElements(CHARACTERS, END_ELEMENT);
return value;
}
public boolean hasNext() throws XMLStreamException {
return reader.hasNext();
}
public void close() throws XMLStreamException {
reader.close();
}
void skipElements(int... elements) throws XMLStreamException {
int eventType = reader.getEventType();
List<Integer> types = asList(elements);
while (types.contains(eventType))
eventType = reader.next();
}
}
伊夫AMSELLEM的答案是相当不错的,但只有当所有元素都完全一样类型的作品。否则,你的unmarshall会抛出一个异常,但读者已经消耗了字节,所以你将无法恢复。相反,我们应该遵循Skaffman的建议并查看来自JAXB jar的示例。
解释它是如何工作的:
- 创建JAXB解组。
- 将侦听器添加到解组器,以截获适当的元素。这是通过“hacking”ArrayList来完成的,以确保元素在解组后不被存储在内存中。
- 创建一个SAX解析器。这是流式传输发生的地方。
- 使用unmarshaller为SAX解析器生成处理程序。
- 流!
我将该解决方案修改为通用*。但是,这需要一些反思。如果这不行,请查看JAXB JARB中的代码示例。
ArrayListAddInterceptor.java
import java.lang.reflect.Field;
import java.util.ArrayList;
public class ArrayListAddInterceptor<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
private AddInterceptor<T> interceptor;
public ArrayListAddInterceptor(AddInterceptor<T> interceptor) {
this.interceptor = interceptor;
}
@Override
public boolean add(T t) {
interceptor.intercept(t);
return false;
}
public static interface AddInterceptor<T> {
public void intercept(T t);
}
public static void apply(AddInterceptor<?> interceptor, Object o, String property) {
try {
Field field = o.getClass().getDeclaredField(property);
field.setAccessible(true);
field.set(o, new ArrayListAddInterceptor(interceptor));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Main.java
public class Main {
public void parsePurchaseOrders(AddInterceptor<PurchaseOrder> interceptor, List<File> files) {
try {
// create JAXBContext for the primer.xsd
JAXBContext context = JAXBContext.newInstance("primer");
Unmarshaller unmarshaller = context.createUnmarshaller();
// install the callback on all PurchaseOrders instances
unmarshaller.setListener(new Unmarshaller.Listener() {
public void beforeUnmarshal(Object target, Object parent) {
if (target instanceof PurchaseOrders) {
ArrayListAddInterceptor.apply(interceptor, target, "purchaseOrder");
}
}
});
// create a new XML parser
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(unmarshaller.getUnmarshallerHandler());
for (File file : files) {
reader.parse(new InputSource(new FileInputStream(file)));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
*此代码尚未经过测试并且仅是为了说明性目的。
- 1. 解析大型XML文件?
- 2. 解析Android中的大型XML文件
- 3. 大型XML文件解析PHP中的块数据扫描
- 4. JAXB解析类似的xml文件
- 5. 解析MySQL的大型XML文件
- 6. 大型文件的Java XML解析器
- 7. 解析非XML文件中的XML块
- 8. 是否有可能中断使用lxml目标解析接口解析中间的大型xml文件?
- 9. 用PL/SQL解析大型XML文件
- 10. 使用Sax解析大型XML文件
- 11. JAXB Vs JDOM:是否有可能使用JAXB更新xml文件
- 12. 使用'xmltodict'模块解析大型XML文件导致OverflowError
- 13. 解析大型XML
- 14. 解析大XML文件
- 15. 是否可以通过JAXB 2.2.x解组非XML数据?
- 16. JAXB XML解析的问题
- 17. 解析android中的大xml文件
- 18. 解析PHP中的巨大XML文件
- 19. 解析XML类型文件
- 20. XML解析器有时无法解析Android上的大型XML文件
- 21. 是否可以从chrome中的不同来源解析xml?
- 22. 是否可以在Android中使用DOM解析器解析特定的XML?
- 23. 使用jaxb解析无效的xml - 解析器可以更宽松吗?
- 24. JAXB XML解析问题
- 25. 使用JAXB解析XML
- 26. 防止在JAXB XML解析
- 27. JAXB解组的XML文档anytype类型
- 28. 用lxml解析大型XML
- 29. 是否可以使用jquery xml解析器修改xml?
- 30. 如何解析分块的XML文件
对,这是我在研究这个网站时发现的网站之一,但我无法找到它在第4.4.1节中提到的“流 - 解组”和“部分解组”。 – 2009-07-15 21:32:58
奇怪。你在看哪里?我刚刚从jaxb.dev.java.net/2.1.12下载了JAR,解压缩了它,在“samples”下面是“partial-unmarshalling”和“stream-unmarshalling”。 – skaffman 2009-07-15 21:42:31