不使用注释的Java代码到XML / XSD

时间:2021-07-21 21:49:24

I need to marshall and unmarshall a Java class to XML. The class in not owned by me, that I cannot add anotations so that I can use JAXB.

我需要将Java类编组并解组为XML。该类不属于我,我无法添加anotations以便我可以使用JAXB。

Is there a good way to convert the Java to XML with the given contraint?

有没有一种很好的方法将Java转换为具有给定约束的XML?

Also, thought a tool may be helpful, but I would be more intersted it there is some Java API to do the same.

此外,认为一个工具可能会有所帮助,但我会更有兴趣它有一些Java API来做同样的事情。

4 个解决方案

#1


16  

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。

DOMAIN MODEL

域模型

I will use the following domain model for this answer. Note how there are no JAXB annotations on the model.

我将使用以下域模型来获得此答案。请注意模型上没有JAXB注释。

Customer

顾客

package forum11693552;

import java.util.*;

public class Customer {

    private String firstName;
    private String lastName;
    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

    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 List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }

}

PhoneNumber

电话号码

package forum11693552;

public class PhoneNumber {

    private String type;
    private String number;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}

OPTION #1 - Any JAXB (JSR-222) Implementation

选项#1 - 任何JAXB(JSR-222)实现

JAXB is configurartion by exception, this means you only need to add annotations where you want the mapping behaviour to differ from the default. Below is a link to an example demonstrating how to use any JAXB impl without annotations:

JAXB是异常配置,这意味着您只需要在希望映射行为与默认值不同的地方添加注释。下面是一个示例的链接,演示如何在没有注释的情况下使用任何JAXB impl:

Demo

演示

package forum11693552;

import javax.xml.bind.*;
import javax.xml.namespace.QName;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Customer customer = new Customer();
        customer.setFirstName("Jane");
        customer.setLastName("Doe");

        PhoneNumber workPhone = new PhoneNumber();
        workPhone.setType("work");
        workPhone.setNumber("555-1111");
        customer.getPhoneNumbers().add(workPhone);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
        marshaller.marshal(rootElement, System.out);
    }

}

Output

产量

<customer>
    <firstName>Jane</firstName>
    <lastName>Doe</lastName>
    <phoneNumbers>
        <number>555-1111</number>
        <type>work</type>
    </phoneNumbers>
</customer>

For More Information

了解更多信息


OPTION #2 - EclipseLink JAXB (MOXy)'s External Mapping Document

选项#2 - EclipseLink JAXB(MOXy)的外部映射文档

If you do want to customize the mappings, then you may be interested in MOXy's external mapping document extension. A sample mapping document looks like the following:

如果您确实想要自定义映射,那么您可能对MOXy的外部映射文档扩展感兴趣。示例映射文档如下所示:

oxm.xml

oxm.xml

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum11693552">
    <java-types>
        <java-type name="Customer">
            <xml-root-element />
            <java-attributes>
                <xml-element java-attribute="firstName" name="first-name" />
                <xml-element java-attribute="lastName" name="last-name" />
                <xml-element java-attribute="phoneNumbers" name="phone-number" />
            </java-attributes>
        </java-type>
        <java-type name="PhoneNumber">
            <java-attributes>
                <xml-attribute java-attribute="type" />
                <xml-value java-attribute="number" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

jaxb.properties

jaxb.properties

To enable MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

要将MOXy作为JAXB提供程序启用,您需要在与域模型相同的程序包中包含一个名为jaxb.properties的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink- MOXY-AS-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

演示

When using EclipseLink MOXy as your JAXB provider (see), you can leverage the external mapping document when you bootstrap your JAXBContext

使用EclipseLink MOXy作为JAXB提供程序(请参阅参考资料)时,可以在引导JAXBContext时利用外部映射文档

package forum11693552;

import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String,Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11693552/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties);

        Customer customer = new Customer();
        customer.setFirstName("Jane");
        customer.setLastName("Doe");

        PhoneNumber workPhone = new PhoneNumber();
        workPhone.setType("work");
        workPhone.setNumber("555-1111");
        customer.getPhoneNumbers().add(workPhone);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
        marshaller.marshal(rootElement, System.out);
    }

}

Output

产量

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <first-name>Jane</first-name>
   <last-name>Doe</last-name>
   <phone-number type="work">555-1111</phone-number>
</customer>

For More Information

了解更多信息

#2


5  

Have you looked at XStream ? It will deserialise/deserialise a standard POJO without annotations or XSDs. You can provide customisations to affect how elements appear in the XML and pretty much works out-of-the-box.

你看过XStream吗?它将对没有注释或XSD的标准POJO进行反序列化/反序列化。您可以提供自定义以影响元素在XML中的显示方式,并且几乎可以开箱即用。

#3


1  

You could write a custom XmlAdapter and annotate fields of the constrained type with a XmlJavaTypeAdapter annotation. The basics would be something like this:

您可以使用XmlJavaTypeAdapter批注编写自定义XmlAdapter并注释约束类型的字段。基础知识将是这样的:

public enum CannotBeAnnotated { value1, value2; }
@XmlRootElement(name="client")
public class ClientClass {
    @XmlJavaTypeAdapter(Bridge.class)
    public CannotBeAnnotated;
}
@XmlRootElement(name="representation")
public class XmlType {
    @XmlValue
    public String value;
}
public class Bridge extends XmlAdapter<XmlType, CannotBeAnnotated>{
    public XmlType marshal(CannotBeAnnotated c) {
        XmlType x=new XmlType(); 
        x.value=c.name();
        return x;
    }
    public CannotBeAnnotated unmarshall(XmlType x) {
        return CannotBeAnnotated.valueOf(x.value);
    }
}

Of course for enums this would not be useful as JAXB knows how to deal with them. I just picked an enum for simplicity so you can see the idea:

当然,对于枚举,这不会有用,因为JAXB知道如何处理它们。我刚刚选择了一个简单的枚举,所以你可以看到这个想法:

  1. Design an XML representation that you do control
  2. 设计您可以控制的XML表示
  3. Write an adapter converting that Java type into the desired type
  4. 编写将该Java类型转换为所需类型的适配器
  5. Annotate "client" code referencing the adapter for the desired type
  6. 注释引用所需类型的适配器的“客户端”代码
  7. Profit.
  8. 利润。

#4


0  

You could also use JibX

你也可以使用JibX

http://jibx.sourceforge.net/

http://jibx.sourceforge.net/

#1


16  

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。

DOMAIN MODEL

域模型

I will use the following domain model for this answer. Note how there are no JAXB annotations on the model.

我将使用以下域模型来获得此答案。请注意模型上没有JAXB注释。

Customer

顾客

package forum11693552;

import java.util.*;

public class Customer {

    private String firstName;
    private String lastName;
    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

    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 List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }

}

PhoneNumber

电话号码

package forum11693552;

public class PhoneNumber {

    private String type;
    private String number;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}

OPTION #1 - Any JAXB (JSR-222) Implementation

选项#1 - 任何JAXB(JSR-222)实现

JAXB is configurartion by exception, this means you only need to add annotations where you want the mapping behaviour to differ from the default. Below is a link to an example demonstrating how to use any JAXB impl without annotations:

JAXB是异常配置,这意味着您只需要在希望映射行为与默认值不同的地方添加注释。下面是一个示例的链接,演示如何在没有注释的情况下使用任何JAXB impl:

Demo

演示

package forum11693552;

import javax.xml.bind.*;
import javax.xml.namespace.QName;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Customer customer = new Customer();
        customer.setFirstName("Jane");
        customer.setLastName("Doe");

        PhoneNumber workPhone = new PhoneNumber();
        workPhone.setType("work");
        workPhone.setNumber("555-1111");
        customer.getPhoneNumbers().add(workPhone);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
        marshaller.marshal(rootElement, System.out);
    }

}

Output

产量

<customer>
    <firstName>Jane</firstName>
    <lastName>Doe</lastName>
    <phoneNumbers>
        <number>555-1111</number>
        <type>work</type>
    </phoneNumbers>
</customer>

For More Information

了解更多信息


OPTION #2 - EclipseLink JAXB (MOXy)'s External Mapping Document

选项#2 - EclipseLink JAXB(MOXy)的外部映射文档

If you do want to customize the mappings, then you may be interested in MOXy's external mapping document extension. A sample mapping document looks like the following:

如果您确实想要自定义映射,那么您可能对MOXy的外部映射文档扩展感兴趣。示例映射文档如下所示:

oxm.xml

oxm.xml

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum11693552">
    <java-types>
        <java-type name="Customer">
            <xml-root-element />
            <java-attributes>
                <xml-element java-attribute="firstName" name="first-name" />
                <xml-element java-attribute="lastName" name="last-name" />
                <xml-element java-attribute="phoneNumbers" name="phone-number" />
            </java-attributes>
        </java-type>
        <java-type name="PhoneNumber">
            <java-attributes>
                <xml-attribute java-attribute="type" />
                <xml-value java-attribute="number" />
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

jaxb.properties

jaxb.properties

To enable MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

要将MOXy作为JAXB提供程序启用,您需要在与域模型相同的程序包中包含一个名为jaxb.properties的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink- MOXY-AS-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

演示

When using EclipseLink MOXy as your JAXB provider (see), you can leverage the external mapping document when you bootstrap your JAXBContext

使用EclipseLink MOXy作为JAXB提供程序(请参阅参考资料)时,可以在引导JAXBContext时利用外部映射文档

package forum11693552;

import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String,Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11693552/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties);

        Customer customer = new Customer();
        customer.setFirstName("Jane");
        customer.setLastName("Doe");

        PhoneNumber workPhone = new PhoneNumber();
        workPhone.setType("work");
        workPhone.setNumber("555-1111");
        customer.getPhoneNumbers().add(workPhone);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
        marshaller.marshal(rootElement, System.out);
    }

}

Output

产量

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <first-name>Jane</first-name>
   <last-name>Doe</last-name>
   <phone-number type="work">555-1111</phone-number>
</customer>

For More Information

了解更多信息

#2


5  

Have you looked at XStream ? It will deserialise/deserialise a standard POJO without annotations or XSDs. You can provide customisations to affect how elements appear in the XML and pretty much works out-of-the-box.

你看过XStream吗?它将对没有注释或XSD的标准POJO进行反序列化/反序列化。您可以提供自定义以影响元素在XML中的显示方式,并且几乎可以开箱即用。

#3


1  

You could write a custom XmlAdapter and annotate fields of the constrained type with a XmlJavaTypeAdapter annotation. The basics would be something like this:

您可以使用XmlJavaTypeAdapter批注编写自定义XmlAdapter并注释约束类型的字段。基础知识将是这样的:

public enum CannotBeAnnotated { value1, value2; }
@XmlRootElement(name="client")
public class ClientClass {
    @XmlJavaTypeAdapter(Bridge.class)
    public CannotBeAnnotated;
}
@XmlRootElement(name="representation")
public class XmlType {
    @XmlValue
    public String value;
}
public class Bridge extends XmlAdapter<XmlType, CannotBeAnnotated>{
    public XmlType marshal(CannotBeAnnotated c) {
        XmlType x=new XmlType(); 
        x.value=c.name();
        return x;
    }
    public CannotBeAnnotated unmarshall(XmlType x) {
        return CannotBeAnnotated.valueOf(x.value);
    }
}

Of course for enums this would not be useful as JAXB knows how to deal with them. I just picked an enum for simplicity so you can see the idea:

当然,对于枚举,这不会有用,因为JAXB知道如何处理它们。我刚刚选择了一个简单的枚举,所以你可以看到这个想法:

  1. Design an XML representation that you do control
  2. 设计您可以控制的XML表示
  3. Write an adapter converting that Java type into the desired type
  4. 编写将该Java类型转换为所需类型的适配器
  5. Annotate "client" code referencing the adapter for the desired type
  6. 注释引用所需类型的适配器的“客户端”代码
  7. Profit.
  8. 利润。

#4


0  

You could also use JibX

你也可以使用JibX

http://jibx.sourceforge.net/

http://jibx.sourceforge.net/