默认命名空间&复杂的包/数据结构 [英] Default namespace & complex package/data structure

查看:77
本文介绍了默认命名空间&复杂的包/数据结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用默认命名空间创建/读取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() + "]");

    }
}

这篇关于默认命名空间&amp;复杂的包/数据结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆