我需要使用默认命名空间创建/读取xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlBoo xmlns="http://www.example2.org/boo">
<customer>
<address>
<street>Wall Street</street>
</address>
<id>1</id>
<name>John</name>
</customer>
<someSpecificField>Specific data in Boo</ns2:someSpecificField>
</xmlBoo>
但我得到了:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:xmlBoo xmlns:ns2="http://www.example2.org/boo">
<ns2:customer>
<address>
<street>Wall Street</street>
</address>
<id>1</id>
<name>John</name>
</ns2:customer>
<ns2:someSpecificField>Specific data in Boo</ns2:someSpecificField>
</ns2:xmlBoo>
我知道package level metadata,但这不适用于复杂的包结构:
我已经定义了类似地址的模型类:
package example.model;
public class Address {
private String street;
客户:
package example.model;
public class Customer {
private long id;
private String name;
private Address address;
公共字段的父类:
package example.xml;
@XmlTransient
public class Xml {
private Customer customer;
然后是具体的类,它包含具体的xml XmlBoo的数据/结构:
package example.xml.boo;
@XmlRootElement
public class XmlBoo extends Xml {
private String someSpecificField;
XmlFoo:
package example.xml.foo;
@XmlRootElement
public class XmlFoo extends Xml {}
package-info.java包含在两个提到的包example.xml.boo中:
@XmlSchema(
namespace = "http://www.example2.org/boo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.boo;
和example.xml.foo:
@XmlSchema(
namespace = "http://www.example2.org/foo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.foo;
最后主要方法:
package example;
public class Demo {
public static void main(String... args) {
generateBoo();
generateFoo();
}
public static void generateBoo() {
try {
JAXBContext jc = JAXBContext.newInstance(XmlBoo.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
XmlBoo xmlBoo = new XmlBoo();
Customer customer = new Customer();
customer.setId(1);
customer.setName("John");
Address address = new Address();
address.setStreet("Wall Street");
customer.setAddress(address);
xmlBoo.setCustomer(customer);
xmlBoo.setSomeSpecificField("Specific data in Boo");
m.marshal(xmlBoo, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
public static void generateFoo() {
try {
JAXBContext jc = JAXBContext.newInstance(XmlFoo.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
XmlFoo xmlFoo = new XmlFoo();
Customer customer = new Customer();
customer.setId(1);
customer.setName("John");
Address address = new Address();
address.setStreet("Wall Street");
customer.setAddress(address);
xmlFoo.setCustomer(customer);
m.marshal(xmlFoo, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
我尝试了here这两种解决方案,也没有成功。
有解决方法我可以删除ns2前缀吗? 我正在使用JDK7。
答案 0 :(得分:3)
解决方法如何获取(写入和读取xml)所需的结果:
<?xml version="1.0" encoding="UTF-8"?>
<xmlBoo xmlns="http://www.example.org/boo" xmlns:c="http://www.example.org/customer" xmlns:a="http://www.example.org/address" xmlns:h="http://www.example.org/header">
<h:header>
<h:id>101</h:id>
</h:header>
<c:customer>
<c:id>1</c:id>
<c:name>Yen</c:name>
<a:address>
<a:street>Long street</a:street>
</a:address>
</c:customer>
<someBooSpecificField>Specific data in Boo</someBooSpecificField>
</xmlBoo>
所以这是解决方案:
定义JAXB的MOXy实现,文件:jaxb.properties
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
为公共字段创建抽象类,为对象定义名称空间,文件Xml.java
package example.xml;
@XmlTransient
public abstract class Xml {
private Header header;
private Customer customer;
@XmlElement(namespace="http://www.example.org/header")
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
@XmlElement(namespace="http://www.example.org/customer")
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
创建“root”类,XmlBoo.java
package example.xml.boo;
@XmlRootElement
@XmlType(propOrder = {"header", "customer", "someBooSpecificField"})
public class XmlBoo extends Xml {
private String someBooSpecificField;
// getter & setter
}
为“root”类设置名称空间和QUALIFIED,文件:example.xml.boo.package-info.java
@XmlSchema(
namespace = "http://www.example.org/boo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.boo;
设置QUALIFIED以生成子项的前缀(命名空间将被类定义的命名空间覆盖,但必须定义),file:example.model.package-info.java
@XmlSchema(
namespace = "http://www.example.org",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.model;
创建Header.java
package example.model;
@XmlType(namespace = "http://www.example.org/header")
public class Header {
private long id;
// getter & setter
}
创建Customer.java
package example.model;
@XmlType(namespace = "http://www.example.org/customer", propOrder = {"id", "name", "address"})
public class Customer {
private long id;
private String name;
private Address address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement(namespace="http://www.example.org/address")
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
创建Address.java
package example.model;
@XmlType(namespace = "http://www.example.org/address")
public class Address {
private String street;
// getter & setter
}
通过扩展org.eclipse.persistence.oxm.NamespacePrefixMapper来创建MyNamespacePrefixMapper.java
package example;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;
public class MyNamespacePrefixMapper extends NamespacePrefixMapper {
private static final String BOO_PREFIX = ""; // DEFAULT NAMESPACE
private static final String BOO_URI = "http://www.example.org/boo";
private static final String FOO_PREFIX = ""; // DEFAULT NAMESPACE
private static final String FOO_URI = "http://www.example.org/foo";
private static final String HEADER_PREFIX = "h";
private static final String HEADER_URI = "http://www.example.org/header";
private static final String CUSTOMER_PREFIX = "c";
private static final String CUSTOMER_URI = "http://www.example.org/customer";
private static final String ADDRESS_PREFIX = "a";
private static final String ADDRESS_URI = "http://www.example.org/address";
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
switch (namespaceUri) {
case BOO_URI:
return BOO_PREFIX;
case FOO_URI:
return FOO_PREFIX;
case HEADER_URI:
return HEADER_PREFIX;
case CUSTOMER_URI:
return CUSTOMER_PREFIX;
case ADDRESS_URI:
return ADDRESS_PREFIX;
default:
return null;
}
}
}
创建XML
public static void generateBoo() {
try {
JAXBContext jc = JAXBContext.newInstance(XmlBoo.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, new MyNamespacePrefixMapper());
XmlBoo xmlBoo = new XmlBoo();
Header header = new Header();
header.setId(101);
xmlBoo.setHeader(header);
Customer customer = new Customer();
customer.setId(1);
customer.setName("Yen");
Address address = new Address();
address.setStreet("Long street");
customer.setAddress(address);
xmlBoo.setCustomer(customer);
xmlBoo.setSomeBooSpecificField("Specific data in Boo");
m.marshal(xmlBoo, System.out);
m.marshal(xmlBoo, new File("xml_boo.xml"));
} catch (JAXBException e) {
e.printStackTrace();
}
}
阅读XML
public static void readBoo() {
Object element = null;
try {
JAXBContext jc = JAXBContext.newInstance(XmlBoo.class);
Unmarshaller u = jc.createUnmarshaller();
element = u.unmarshal(new File("xml_boo.xml"));
} catch (JAXBException e) {
e.printStackTrace();
}
if (element instanceof XmlBoo) {
XmlBoo xmlBoo = (XmlBoo) element;
Customer customer = xmlBoo.getCustomer();
System.out.println("INFO | xmlBoo field: [" + xmlBoo.getSomeBooSpecificField() + "]");
System.out.println("INFO | customer name: [" + customer.getName() + "]");
System.out.println("INFO | address street: [" + customer.getAddress().getStreet() + "]");
}
}
答案 1 :(得分:2)
我使用EclipseLink MOXy JAXB实现而不是RI Metro JAXB,现在它可以工作了。所以看起来在Metro中是错误的。
Blaise Doughan的完美教程:JAXB & Namespace prefixes
答案 2 :(得分:1)
您需要为域模型中的每个包提供一个带有package-info
注释的@XmlSchema
注释,每个包指定相同的命名空间限定以获取所需的XML。