默认命名空间&复杂的包/数据结构 [英] Default namespace & complex package/data structure
问题描述
我需要使用默认命名空间创建/读取xml文件:
<?xml version =1.0encoding = UTF-8standalone =yes?>
< xmlBoo xmlns =http://www.example2.org/boo>
< customer>
< address>
< street>华尔街< / street>
< / address>
< id> 1< / id>
< name> John< / name>
< / customer>
< someSpecificField> Boo< / ns2:someSpecificField>中的特定数据
< / xmlBoo>
但我得到:
<?xml version =1.0encoding =UTF-8standalone =yes?>
< ns2:xmlBoo xmlns:ns2 =http://www.example2.org/boo>
< ns2:customer>
< address>
< street>华尔街< / street>
< / address>
< id> 1< / id>
< name> John< / name>
< / ns2:customer>
< ns2:someSpecificField> Boo< / ns2:someSpecificField>中的特定数据
< / ns2:xmlBoo>
我知道也没有成功。
- 可以删除&如果我在一个包中有所有类(和一个包信息文件),则重命名前缀
- 如果我有复杂的包结构,可以重命名但不删除前缀
是否有解决方案如何删除ns2前缀?
我正在使用JDK7。
解决方法如何获取(写入和读取xml)所需的结果:
<?xml version =1.0encoding =UTF-8?>
< xmlBoo xmlns =http://www.example.org/booxmlns:c =http://www.example.org/customerxmlns:a =http:// www。 example.org/addressxmlns: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:地址>
< a:street>长街< / a:street>
< / a:地址>
< / c:customer>
< someBooSpecificField> Boo< / someBooSpecificField>中的特定数据
< / xmlBoo>
- 对于根元素及其简单子节点使用默认命名空间(没有前缀)
- 对于复杂(java中的对象)子项使用不同的名称空间(映射到不同的前缀)
- 模型类在不同的包中
所以这是解决方案:
定义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;
私人客户客户;
@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(客户客户){
this.customer = customer;
}
}
创建root类,XmlBoo.java
package example.xml.boo;
@XmlRootElement
@XmlType(propOrder = {header,customer,someBooSpecificField})
公共类XmlBoo扩展Xml {
private String someBooSpecificField;
// getter& setter
}
为root类设置名称空间和QUALIFIED,file:example.xml .boo.package-info.java
@XmlSchema(
namespace =http://www.example。 org / boo,
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.boo;
设置QUALIFIED以生成子项的前缀(命名空间将被定义的名称空间覆盖class,但必须定义),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 {
私人长身份;
私有字符串名称;
私人地址;
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)
公共地址getAddress(){
返回地址;
}
public void setAddress(地址){
this.address = address;
}
}
创建Address.java
package example.model;
@XmlType(namespace =http://www.example.org/address)
公共类地址{
private String street;
// getter& setter
}
通过扩展org.eclipse.persistence.oxm.NamespacePrefixMapper创建MyNamespacePrefixMapper.java
包示例;
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:
返回BOO_PREFIX;
case FOO_URI:
返回FOO_PREFIX;
case HEADER_URI:
返回HEADER_PREFIX;
case CUSTOMER_URI:
返回CUSTOMER_PREFIX;
case ADDRESS_URI:
return ADDRESS_PREFIX;
默认值:
返回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.setId(101);
xmlBoo.setHeader(header);
客户客户=新客户();
customer.setId(1);
customer.setName(Yen);
地址=新地址();
address.setStreet(长街);
customer.setAddress(address);
xmlBoo.setCustomer(customer);
xmlBoo.setSomeBooSpecificField(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 = xmlBoo.getCustomer();
System.out.println(INFO | xmlBoo field:[+ xmlBoo.getSomeBooSpecificField()+]);
System.out.println(INFO |客户名称:[+ customer.getName()+]);
System.out.println(INFO | address street:[+ customer.getAddress()。getStreet()+]);
}
}
I need create/read xml file using default namespace:
<?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>
but I'm getting:
<?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>
I know about package level metadata, but this is not working in complex package structure:
I have defined model classes like Address:
package example.model;
public class Address {
private String street;
Customer:
package example.model;
public class Customer {
private long id;
private String name;
private Address address;
The parent class for common fields:
package example.xml;
@XmlTransient
public class Xml {
private Customer customer;
Then specific classes which holds data/structure of concrete 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 is included in two mentioned packages example.xml.boo:
@XmlSchema(
namespace = "http://www.example2.org/boo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.boo;
and example.xml.foo:
@XmlSchema(
namespace = "http://www.example2.org/foo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.foo;
And finally main method:
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();
}
}
}
I've tried both solutions like here and also without success.
- It is possible remove & rename prefix if I have all classes in one package (and one package-info file)
- It is possible rename but NOT remove prefix if I have complex package structure
Is there solution how I can remove ns2 prefix? I'm using JDK7.
Solution how get (write & read xml) the needed result:
<?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>
- for root element and its "simple" children is used default namespace (without prefix)
- for complex (objects in java) children are used different namespaces (mapped to different prefixes)
- model classes are in different packages
So here is the solution:
Define MOXy implementation of JAXB, file: jaxb.properties
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Create abstract class for common fields, define namespace for object, file 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;
}
}
Create "root" class, XmlBoo.java
package example.xml.boo;
@XmlRootElement
@XmlType(propOrder = {"header", "customer", "someBooSpecificField"})
public class XmlBoo extends Xml {
private String someBooSpecificField;
// getter & setter
}
Set namespace and QUALIFIED for "root" class, file: example.xml.boo.package-info.java
@XmlSchema(
namespace = "http://www.example.org/boo",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.xml.boo;
Set QUALIFIED to generate prefix for children (the namespace will be overridden by namespace defined on the class, but it must be defined), file: example.model.package-info.java
@XmlSchema(
namespace = "http://www.example.org",
elementFormDefault = XmlNsForm.QUALIFIED)
package example.model;
Create Header.java
package example.model;
@XmlType(namespace = "http://www.example.org/header")
public class Header {
private long id;
// getter & setter
}
Create 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;
}
}
Create Address.java
package example.model;
@XmlType(namespace = "http://www.example.org/address")
public class Address {
private String street;
// getter & setter
}
Create MyNamespacePrefixMapper.java by extending org.eclipse.persistence.oxm.NamespacePrefixMapper
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;
}
}
}
Create 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();
}
}
Read 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() + "]");
}
}
这篇关于默认命名空间&复杂的包/数据结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!