不使用注解的 Java 代码到 XML/XSD
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11693552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Code to XML/XSD without using Annotation
提问by Sandeep Jindal
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。该类不属于我,我无法添加注释以便我可以使用 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 可以做同样的事情。
回答by bdoughan
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 实现:
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
想要查询更多的信息
回答by Brian Agnew
回答by user268396
You could write a custom XmlAdapter
and annotate fields of the constrained type with a XmlJavaTypeAdapter
annotation. The basics would be something like this:
您可以XmlAdapter
使用注释编写约束类型的自定义和注释字段XmlJavaTypeAdapter
。基本原理是这样的:
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 知道如何处理它们。为了简单起见,我只是选择了一个枚举,以便您可以看到这个想法:
- Design an XML representation that you docontrol
- Write an adapter converting that Java type into the desired type
- Annotate "client" code referencing the adapter for the desired type
- Profit.
- 设计一个您可以控制的 XML 表示
- 编写一个将该 Java 类型转换为所需类型的适配器
- 注释引用所需类型的适配器的“客户端”代码
- 利润。