我需要解析潛在的大型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