JAXB:删除父节点,保留其子节点。

问题描述 投票:0回答:1

我知道这没有什么意义,但是我必须从一个Java对象中生成一个没有某些元素的父节点的XML,就像下面解释的那样。

这是XML的Java类模型的例子。

@XmlRootElement(name = "person")
public class PersonXml {

    @XmlElement(name = "name")
    private String name;

    @XmlElement(name = "car")
    private List<CarXml> cars;

.

@XmlRootElement(name = "car")
public class CarXml {

    @XmlElement(name = "model")
    private String model;

    @XmlElement(name = "brand")
    private String brand;

默认情况下,如果我从一个对象中生成XML,那么这个对象的名字是 PersonXml 像这样。

StringWriter writer = new StringWriter();

JAXBContext ctx = JAXBContext.newInstance(PersonXml.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.marshal(xml, writer);

我会得到。

<person>
    <name>Pedro</name>
    <car>
        <model>Logan</model>
        <brand>Renault</brand>
    </car>
    <car>
        <model>Duster</model>
        <brand>Renault</brand>
    </car>
</person>

我需要做的是删除 <car> 标签,甚至根本无法生成它。

我需要XML是这样的。

<person>
    <name>Pedro</name>
    <model>Logan</model>
    <brand>Renault</brand>
    <model>Duster</model>
    <brand>Renault</brand>
</person>

当然,我可以把XML转换成一个字符串 然后把标签删除掉 replaceAll 或类似的东西,但我想知道是否有更好的方法来实现这一点。

java xml jaxb marshalling
1个回答
0
投票

如果你需要生成这种输出,你可以使用JAXB,如下。

1) 创建一个新的 Person 类。

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "field"
})
@XmlRootElement(name = "person")
public class Person {

    @XmlElementRefs({
        @XmlElementRef(name = "name", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "model", type = JAXBElement.class, required = false),
        @XmlElementRef(name = "brand", type = JAXBElement.class, required = false)
    })
    protected List<JAXBElement<String>> field;

    public List<JAXBElement<String>> getNameOrModelOrBrand() {
        if (field == null) {
            field = new ArrayList<>();
        }
        return this.field;
    }

}

2)创建一个 ObjectFactory 以方便人类的使用。

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    private final static QName _PersonName_QNAME = new QName("", "name");
    private final static QName _PersonModel_QNAME = new QName("", "model");
    private final static QName _PersonBrand_QNAME = new QName("", "brand");

    public ObjectFactory() {
    }

    public Person createPerson() {
        return new Person();
    }

    @XmlElementDecl(namespace = "", name = "name", scope = Person.class)
    public JAXBElement<String> createPersonName(String value) {
        return new JAXBElement<>(_PersonName_QNAME, String.class, Person.class, value);
    }

    @XmlElementDecl(namespace = "", name = "model", scope = Person.class)
    public JAXBElement<String> createPersonModel(String value) {
        return new JAXBElement<>(_PersonModel_QNAME, String.class, Person.class, value);
    }

    @XmlElementDecl(namespace = "", name = "brand", scope = Person.class)
    public JAXBElement<String> createPersonBrand(String value) {
        return new JAXBElement<>(_PersonBrand_QNAME, String.class, Person.class, value);
    }

}
  1. 使用工厂如下。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;
import java.util.List;

...

ObjectFactory factory = new ObjectFactory();

Person person = factory.createPerson();
List<JAXBElement<String>> list = person.getNameOrModelOrBrand();
list.add(factory.createPersonName("Pedro"));
list.add(factory.createPersonModel("Logan"));
list.add(factory.createPersonBrand("Renault"));
list.add(factory.createPersonModel("Duster"));
list.add(factory.createPersonBrand("Renault"));

JAXBContext ctx = JAXBContext.newInstance(Person.class);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter writer = new StringWriter();
marshaller.marshal(person, writer);
System.out.println(writer.toString());

最终结果是XML如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <name>Pedro</name>
    <model>Logan</model>
    <brand>Renault</brand>
    <model>Duster</model>
    <brand>Renault</brand>
</person>

以这种方式创建元素是我所知道的唯一能得到你所需要的最终结果的方法。

也许你可以做各种事情来重构上面的代码,以简化元素列表的创建--但这向你展示了基本的方法。

正如你已经知道的那样--这远非理想。最终的结果并不是我想要接收的任何类型的XML。

© www.soinside.com 2019 - 2024. All rights reserved.