用外部节点写一个 xml 文件
Write an xml file with external nodes
我需要生成一个结构简单的大 xml 文件
<file>
<details>
<d1></d1>
...
<dn></dn>
<task></task>
<task></task>
...
<task></task>
</details>
</file>
我将 JAXB 用于 Xml - POJO 映射。所以我有一个包含任务列表的 FilePojo。这些任务存储在数据库中,因为它们数量很多,所以我不能一次将它们全部检索到内存中。
如何执行元帅操作?
到目前为止,我使用 XMLStreamWriter
与此操作相关的代码
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter xmlsw = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writerXml));
JAXBContext jc = JAXBContext.newInstance(File.class);
Marshaller m = jc.createMarshaller();
JAXBElement<File> jx = new JAXBElement<>(new QName("http://namespace", "File"), File.class, file);
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.marshal(jx, xmlsw);
文件对象包含除任务列表之外的所有详细信息。
考虑这个冗长的示例(编译和 运行 - 包括所有 classes)。
在此示例中,class Details
包含两个列表(不确定您有什么)- 一个带有任务 - 但没有注释,因此不会在 JAXB 中使用,另一个带有TaskId
个仅包含对一项任务的引用的对象。我为 TaskId 对象添加了自定义 Marshaller,并告诉 JAXB 将它们写为 "task"。如果 JAXB 流出输出,您应该能够使用此代码执行 "load one at a time"。如果 JAXB 缓冲所有输出,您将不得不考虑其他方式来生成 XML,正如您所说,您无法将所有任务加载到内存中。
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.JOptionPane;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import my.test.XmlOut.TaskId;
import my.test.XmlOut.TaskListAdapter;
import my.test.XmlOut.File.Details;
import my.test.XmlOut.File.Task;
import my.test.XmlOut.File.TaskList;
public class XmlOut {
public static class TaskId {
}
public static class TaskListAdapter extends XmlAdapter<String,TaskId> {
@Override
public TaskId unmarshal(String v) throws Exception {
// TODO Auto-generated method stub
return null;
}
@Override
public String marshal(TaskId v) throws Exception {
//Load your actual TASK here and convert it to XML (you could use JAXB as well)
return "HERE GOES MY TASK XML";
}
}
@XmlRootElement
public static class File {
public static class TaskList {
int fileid;
}
public static class Task {
String id;
@XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
public static class Details {
String d1;
String dn;
private List<Task> tasks;
private List<TaskId> taskIds;
public void setTasks(List<Task> t) {
tasks = t;
}
@XmlElement
public String getD1() {
return d1;
}
public void setD1(String d1) {
this.d1 = d1;
}
@XmlElement
public String getDn() {
return dn;
}
public void setDn(String dn) {
this.dn = dn;
}
@XmlElement(name="task")
@XmlJavaTypeAdapter(TaskListAdapter.class)
public List<TaskId> getTaskIds() {
return taskIds;
}
public void setTaskIds(List<TaskId> asList) {
taskIds = asList;
}
}
protected Details details = new Details();
@XmlElement
public Details getDetails() {
return details;
}
public void setDetails(Details details) {
this.details = details;
}
}
public static void main(String[] args) {
try {
File file = new File();
file.setDetails(new Details());
file.getDetails().setD1("d1");
file.getDetails().setTaskIds(Arrays.asList(new TaskId(), new TaskId(), new TaskId(), new TaskId(),
new TaskId(), new TaskId(), new TaskId()));
XMLOutputFactory factory = XMLOutputFactory.newInstance();
JAXBContext jc = JAXBContext.newInstance(File.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
JAXBElement<File> jx = new JAXBElement<>(new QName("http://namespace", "File"), File.class, file);
m.marshal(jx, System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
我需要生成一个结构简单的大 xml 文件
<file>
<details>
<d1></d1>
...
<dn></dn>
<task></task>
<task></task>
...
<task></task>
</details>
</file>
我将 JAXB 用于 Xml - POJO 映射。所以我有一个包含任务列表的 FilePojo。这些任务存储在数据库中,因为它们数量很多,所以我不能一次将它们全部检索到内存中。
如何执行元帅操作?
到目前为止,我使用 XMLStreamWriter
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter xmlsw = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writerXml));
JAXBContext jc = JAXBContext.newInstance(File.class);
Marshaller m = jc.createMarshaller();
JAXBElement<File> jx = new JAXBElement<>(new QName("http://namespace", "File"), File.class, file);
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.marshal(jx, xmlsw);
文件对象包含除任务列表之外的所有详细信息。
考虑这个冗长的示例(编译和 运行 - 包括所有 classes)。
在此示例中,class Details
包含两个列表(不确定您有什么)- 一个带有任务 - 但没有注释,因此不会在 JAXB 中使用,另一个带有TaskId
个仅包含对一项任务的引用的对象。我为 TaskId 对象添加了自定义 Marshaller,并告诉 JAXB 将它们写为 "task"。如果 JAXB 流出输出,您应该能够使用此代码执行 "load one at a time"。如果 JAXB 缓冲所有输出,您将不得不考虑其他方式来生成 XML,正如您所说,您无法将所有任务加载到内存中。
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.swing.JOptionPane;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import my.test.XmlOut.TaskId;
import my.test.XmlOut.TaskListAdapter;
import my.test.XmlOut.File.Details;
import my.test.XmlOut.File.Task;
import my.test.XmlOut.File.TaskList;
public class XmlOut {
public static class TaskId {
}
public static class TaskListAdapter extends XmlAdapter<String,TaskId> {
@Override
public TaskId unmarshal(String v) throws Exception {
// TODO Auto-generated method stub
return null;
}
@Override
public String marshal(TaskId v) throws Exception {
//Load your actual TASK here and convert it to XML (you could use JAXB as well)
return "HERE GOES MY TASK XML";
}
}
@XmlRootElement
public static class File {
public static class TaskList {
int fileid;
}
public static class Task {
String id;
@XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
public static class Details {
String d1;
String dn;
private List<Task> tasks;
private List<TaskId> taskIds;
public void setTasks(List<Task> t) {
tasks = t;
}
@XmlElement
public String getD1() {
return d1;
}
public void setD1(String d1) {
this.d1 = d1;
}
@XmlElement
public String getDn() {
return dn;
}
public void setDn(String dn) {
this.dn = dn;
}
@XmlElement(name="task")
@XmlJavaTypeAdapter(TaskListAdapter.class)
public List<TaskId> getTaskIds() {
return taskIds;
}
public void setTaskIds(List<TaskId> asList) {
taskIds = asList;
}
}
protected Details details = new Details();
@XmlElement
public Details getDetails() {
return details;
}
public void setDetails(Details details) {
this.details = details;
}
}
public static void main(String[] args) {
try {
File file = new File();
file.setDetails(new Details());
file.getDetails().setD1("d1");
file.getDetails().setTaskIds(Arrays.asList(new TaskId(), new TaskId(), new TaskId(), new TaskId(),
new TaskId(), new TaskId(), new TaskId()));
XMLOutputFactory factory = XMLOutputFactory.newInstance();
JAXBContext jc = JAXBContext.newInstance(File.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
JAXBElement<File> jx = new JAXBElement<>(new QName("http://namespace", "File"), File.class, file);
m.marshal(jx, System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}