如何在XStream或JAXB上将两个XML元素级别映射到一个级别?

时间:2016-10-15 07:30:12

标签: java xml jaxb mapping xstream

我在将两个级别的XML元素映射到Java Bean中的一个级别时遇到了一些困难。这是我的上下文,我有一个像这样的XML:

<?xml version='1.0' encoding="utf-8" ?>
<Employee>
    <Data>
        <CompanyId>1</CompanyId>
        <FirstName>John</FirstName>
        <LastName>Oliver</LastName>
        <DOB>1986-21-07</DOB>
    </Data>
</Employee>

这是我的Java Bean:

@XStreamAlias("Employee/Data")
public  class Employee {
    @XStreamAlias("CompanyId") private int companyId;
    @XStreamAlias("FirstName") private String firstName;
    @XStreamAlias("LastName")  private String lastName;
    @XStreamAlias("DOB")       private LocalDate birthDate;
    public int getCompanyId() { return companyId; }
    public void setCompanyId(int companyId) { this.companyId = companyId; }
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    public LocalDate getBirthDate() { return birthDate; }
    public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; }
}

我将XML元素分隔为&#34; /&#34;只是为了说明我想要如何映射,但似乎XStream不能以这种方式工作。使用注释映射的任何技巧还是应该编写自定义转换器?如果有人知道如何在JAXB中进行这种映射也是受欢迎的。

1 个答案:

答案 0 :(得分:0)

我找到了一个使用JAXB + eclipselink moxy的解决方案。首先添加eclipselink依赖项'org.eclipse.persistence:org.eclipse.persistence.moxy:2.6.4'并确保您在应用程序中使用eclipselink实现,您需要通过命令行传递JVM参数

-Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

或者像我一样在你的方法主要设置:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDate;
import java.time.Month;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Employee")
public class Employee {

    @XmlPath("Data/CompanyId/text()") private int companyId;
    @XmlPath("Data/FirstName/text()") private String firstName;
    @XmlPath("Data/LastName/text()")  private String lastName;
    @XmlPath("Data/DOB/text()")       private LocalDate birthDate;

    public int getCompanyId() { return companyId; }
    public void setCompanyId(int companyId) { this.companyId = companyId; }
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    public LocalDate getBirthDate() { return birthDate; }
    public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; }

    public String toString() {
        return String.format("{companyId: %d, firstName: \"%s\", lastName: \"%s\"}", companyId, firstName, lastName);
    }


    public static void main(String[] args) throws Exception {

        System.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory");

        Employee employee = new Employee();
        employee.setCompanyId(100);
        employee.setFirstName("Michael");
        employee.setLastName("Hoffmann");
        employee.setBirthDate(LocalDate.of(1970,  Month.JANUARY, 19));

        JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
        StringWriter sw = new StringWriter();
        PrintWriter out = new PrintWriter(sw);

        jaxbContext.createMarshaller().marshal(employee, out);
        out.flush();
        String xml = sw.toString();
        System.out.println(xml);

        InputStream in = new ByteArrayInputStream(xml.getBytes());


        Employee employee2 = (Employee) jaxbContext.createUnmarshaller().unmarshal(in);
        System.out.println(employee2);

    }

}