【问题标题】:Write an xml file with external nodes使用外部节点编写 xml 文件
【发布时间】:2015-11-26 11:45:11
【问题描述】:

我需要生成一个结构简单的大型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);

文件对象包含除任务列表之外的所有详细信息。

【问题讨论】:

  • 棘手。您能否分享您的 POJO for File 以及任务列表如何适应它?我最好的猜测是不映射您的 List 而是提供一些 List 您可以保留在内存中(仅您的任务的 ID),然后在 TaskKey 上提供基于 XmlMapper 的自定义编组器以从 DB 中提取数据需要。但这仍然假设内容将被写入底层流上的每个字段 - 而不仅仅是在所有编组完成后返回的缓冲区......
  • @Jan 我没有确切的 POJO,因为这是对真实系统的简化。您能否给我更多有关自定义编组器的详细信息?这将如何运作?

标签: java jaxb stax


【解决方案1】:

考虑这个冗长的示例(编译并运行 - 包括所有类)。

在这个例子中,Details 类包含两个列表(不确定你有什么) - 一个带有任务 - 但没有注释,因此不会在 JAXB 中使用,另一个带有 TaskId 对象,只包含一个参考一项任务。我为 TaskId 对象添加了自定义 Marshaller,并告诉 JAXB 将它们写为“任务”。如果 JAXB 将输出流式输出,您应该能够使用此代码“一次加载一个”。如果 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();
    }
  }
}

【讨论】:

  • 谢谢你。我们不能在执行您的示例后确定 JAXB 是否流式传输或缓冲输出?
  • 在TaskItem Marshaller中不会产生一些最小的数据输出。但是可能有内部缓冲区在满时被刷新..? O
猜你喜欢
  • 2018-04-24
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 2011-04-25
相关资源
最近更新 更多