[英]Unmarshal big xml files using JAXB
我有 1-2MB xml 個文件,我想將它們加載到對象列表中。 我想通過 JAXB 來完成,因為我有合適的 XSD,只有在加載這些文件時才會出現問題,因為它會拋出錯誤,說某處有未關閉的標簽,或者類似的東西,當我檢查文件時,沒有那里的錯誤。 當我加載大小為 40KB 的文件時,沒有問題,一切都在正確加載。 所以我知道在解組較大文件時 jaxb 中存在問題。 這個有什么吃法嗎? 另一種解組方式不太可能包含在游戲中,因為每個 xml 文件的結構和對象都與我用 XSD 創建的略有不同。
xml個文件的結構:
<Request>
<Header>
<Name> </Name>
<Id> </Id>
</Header>
<RequestItems>
<Request>
<Header>
<Name> </Name>
<Id> </Id>
</Header>
<ObjectName>
<City> </City>
<Street> </Street>
</ObjectName>
</Request>
</RequestItems>
</Request>
在 RequestItems 標簽內有一個 Request 對象列表,在 Request ObjectName 對象中它因文件而異。
我以最簡單的方式執行 unmrashal,對於較小的文件,它工作正常,而較大的文件有奇怪的語法錯誤,但我知道它只是削減行,因為它太長,因此存在語法錯誤。
JAXBContext jaxbContext = JAXBContext.newInstance (Request.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller ();
Request request = (Request) jaxbUnmarshaller.unmarshal (xmlFile);
如果我正確理解了您的問題,那么這應該可行。 我使用了 Moxy,它是 Jaxb 的擴展和 Project Lombok 的 Getter setter。
想象以下是具有不同結構request.xml
的大型 XML :
<request>
<person>
<name>Batman</name>
<age>29</age>
<job>IT</job>
</person>
<animal>
<name>Tommy</name>
<age>5</age>
<type>Dog</type>
</animal>
<person>
<name>Superman</name>
<age>30</age>
<job>HR</job>
</person>
</request>
以下是相關的類和接口:
import jakarta.xml.bind.annotation.XmlSeeAlso;
@XmlSeeAlso({Person.class, Animal.class})
public interface XmlSupportExtension {
Object xmlSupport();
}
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
public class Common implements Serializable {
private String name;
private String age;
}
import lombok.*;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person extends Common implements XmlSupportExtension {
private String job;
@Override
public Person xmlSupport() {
return this;
}
}
import lombok.*;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class Animal extends Common implements XmlSupportExtension {
private String type;
@Override
public Animal xmlSupport() {
return this;
}
}
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;
public class MainStack {
public static void main(String[] args) throws JAXBException, XMLStreamException, FileNotFoundException {
final String[] EVENT_TYPES = new String[]{"person", "animal"};
InputStream inputStream = MainStack.class.getResourceAsStream("/request.xml");
//Create an instance of XMLStreamReader to read the events one-by-one
final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
final XMLStreamReader xmlStreamReader = inputFactory.createXMLStreamReader(inputStream);
//Create an instance of JAXBContext and Unmarshaller for unmarshalling the classes to respective event
final Unmarshaller unmarshaller = JAXBContext.newInstance(Person.class, Animal.class).createUnmarshaller();
//Navigate to next and start of the XML Elements
xmlStreamReader.next();
//Read Until the end of the file and unmarshall event-by-event
while (xmlStreamReader.hasNext()) {
//Check if the initial element is one of the elements from "EVENT_TYPES"
if (xmlStreamReader.isStartElement() && Arrays.asList(EVENT_TYPES).contains(xmlStreamReader.getLocalName())) {
//Get the event type
final String eventType = xmlStreamReader.getLocalName();
Object event = null;
System.out.println(eventType);
// Based on eventType make unmarshaller call to respective event class
switch (eventType) {
case "person":
//Unmarshal the Person
event = unmarshaller.unmarshal(xmlStreamReader, Person.class).getValue();
break;
case "animal":
//Unmarshal the Animal
event = unmarshaller.unmarshal(xmlStreamReader, Animal.class).getValue();
break;
default:
//If NONE of the event type matches then do not convert and make a note
System.out.println("XML event does not match any of the required event : " + event);
break;
}
System.out.println(" After Unmarhsalling : " + event.toString());
}
//Move to the next event/element in InputStream
xmlStreamReader.next();
}
}
}
這將產生以下 output:
person
After Unmarhsalling : Person(super=Common(name=Batman, age=29), job=IT)
animal
After Unmarhsalling : Animal(super=Common(name=Tommy, age=5), type=Dog)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.