【问题标题】:distinct XML mapping/binding on the same Java object同一 Java 对象上的不同 XML 映射/绑定
【发布时间】:2015-06-28 21:47:36
【问题描述】:

我有一个可与其他几个信息系统互操作的 Java 应用程序

同一个对象可以根据目标信息系统映射到不同的XML文件中

我的问题是:是否有 Java 解决方案可以在同一个对象上执行多个 XML 映射/绑定

类似于 Bean 验证组的东西,可以使用不同的验证配置文件验证对象

在 JAXB 样式中,它可能是这样的,例如:

// pseudocode
@XmlRootElement(name="person", , profile="profile1")
@XmlRootElement(name="individual", profile="profile2")
@XmlRootElement(name="human", profile="profile3")
public class Person {

    @XmlElement(name = "lastName", profile="profile1")
    @XmlElement(name = "surname", profile="profile2")
    @XmlElement(name = "famillyName", profile="profile3")
    private String lastName;

    //...
}

然后

    // pseudocode
    File file = new File("C:\\file.xml");
    JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller("profile1");
    jaxbMarshaller.marshal(person, file);

    //...

    File file = new File("C:\\file.xml");
    JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller("profile1");
    Person person = (Person) jaxbUnmarshaller.unmarshal(file);

也许可以用 JAXB 做这样的事情,但我不知道


编辑

@Martin Serrano 的回复为我提供了一些使用 JAXB 优化事物的线索。

一个统治它们的抽象类:

@XmlTransient
public abstract class APerson {

    protected String lastname;

    public APerson() {
    }

    public APerson(APerson p) {
        lastname = p.lastname;
    }

    public abstract String getLastname();

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + "{" + lastname + "}";
    }
}

并具体化进行映射的类:

默认映射的类Person

@XmlRootElement
public class Person extends APerson {

    public Person() {
    }

    public Person(APerson p) {
        super(p);
    }

    @Override
    public String getLastname() {
        return lastname;
    }
}

以及其他用于替代映射的类:

@XmlRootElement
public class Human extends APerson {

    public Human() {
    }

    public Human(APerson p) {
        super(p);
    }

    @Override
    @XmlElement(name = "famillyName")
    public String getLastname() {
        return lastname;
    }
}


@XmlRootElement
public class Individual extends APerson{   

    public Individual() {
    }

    public Individual(APerson p) {
        super(p);
    }    

    @Override
    @XmlElement(name = "surname")
    public String getLastname() {
        return lastname;
    }
}

然后进行测试:

public class Main {

    public static void main(String[] args) throws Exception {
        Person person = new Person();
        person.setLastname("Doe");

        String fileName = "person.xml";
        marshal(person, fileName);
        person = unmarshal(Person.class, fileName);
        System.out.println(person);

        fileName = "human.xml";
        Human human = new Human(person);
        marshal(human, fileName);
        human = unmarshal(Human.class, fileName);
        System.out.println(human);
        person = new Person(human);
        System.out.println(person);

        fileName = "individual.xml";
        Individual individual = new Individual(person);
        marshal(individual, fileName);
        individual = unmarshal(Individual.class, fileName);
        System.out.println(individual);
        person = new Person(individual);
        System.out.println(person);
    }

    private static <P extends APerson> void marshal(P person, String fileName) throws JAXBException {
        File file = new File(fileName);
        JAXBContext context = JAXBContext.newInstance(person.getClass());
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(person, file);
        marshaller.marshal(person, System.out);
    }

    private static <P extends APerson> P unmarshal(Class<P> cl, String fileName) throws JAXBException {
        File file = new File(fileName);
        JAXBContext context = JAXBContext.newInstance(cl);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        P person = (P) unmarshaller.unmarshal(file);
        return person;
    }

}

结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
    <lastname>Doe</lastname>
</person>
Person{Doe}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human>
    <famillyName>Doe</famillyName>
</human>
Human{Doe}
Person{Doe}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<individual>
    <surname>Doe</surname>
</individual>
Individual{Doe}
Person{Doe}

我发现最好的解决方案是具有不同的映射并避免代码重复,因此我们只需使用映射实现 getter。

让我们看看它是否在解决更大的问题!

虽然它比拥有 3 个不同的类要好得多,但它仍然不是同一个类上的 3 个映射......

【问题讨论】:

    标签: java xml xml-binding oxm


    【解决方案1】:

    执行此类操作的最简单方法是为每个系统使用不同的外观。这将允许您更改 JAXB 反序列化对象的方式。它还允许您根据相关系统进行其他转换和调整。基类 Person 将具有您的默认序列化,并且每个系统都可以在必要时使用适合它的外观。这基本上是mapping interfaces 上的非官方 jaxb 指南中概述的方法。

    可以为每个系统注册这样的外观,使您可以将系统特定的配置文件排除在每个核心类型的代码之外。

    使用您的示例,核心界面将是:

    @XmlRootElement(name="person")
    public interface Person {
      @XmlElement(name = "lastName")
      private String lastName;
    }
    

    那么对于 System1,您将拥有:

    @XmlRootElement(name="individual")
    public class Individual implements Person {
    }
    

    另一个系统可能有:

    @XmlRootElement(name="human")
    public class Human implements Person {
    }
    

    【讨论】:

    • 我不太明白,你的意思是我会有一个类 Person 带有 profile1 映射,还有一个类 Individual 带有对应于 profile2 的映射使用一个类应用程序,假设Person,并将Person 转换为Individual 以获取与profile2 对应的XML,反之亦然? (例如使用 PersonIndividual 之间的 bean 到 bean 映射)
    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 2015-04-15
    • 2012-08-06
    • 2015-08-19
    • 1970-01-01
    相关资源
    最近更新 更多