java xml jaxb_Java XML操作之JAXB命名空间及命名空间前缀处理

本文介绍了如何使用JAXB在Java中处理XML命名空间和命名空间前缀。通过`@XmlSchema`注解和`package-info.java`文件可以设置全局命名空间前缀,但这种方法不灵活。推荐的方法是实现`NamespacePrefixMapper`,重写`getPreferredPrefix`方法,以自定义每个实体类的命名空间前缀。示例代码展示了如何序列化和反序列化XML时控制命名空间前缀。
摘要由CSDN通过智能技术生成

命名空间前缀处理

相信大名鼎鼎的ns2,nsXX让很多人非常头疼类似下面这样的

69c5a8ac3fa60e0848d784a6dd461da6.png<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

11

A1

22

B2

69c5a8ac3fa60e0848d784a6dd461da6.png

69c5a8ac3fa60e0848d784a6dd461da6.png@XmlSchema( xmlns = { @XmlNs(namespaceURI = "http://www.lzrabbit.cn", prefix = "rabbit"), @XmlNs(namespaceURI = "http://www.cnblogs.com", prefix = "blog")})packagecn.lzrabbit;importjavax.xml.bind.annotation.XmlSchema;import javax.xml.bind.annotation.XmlNs;

69c5a8ac3fa60e0848d784a6dd461da6.png

ClassA如下

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

packagecn.lzrabbit;import javax.xml.bind.annotation.*;

@XmlRootElement(namespace="http://www.lzrabbit.cn")

@XmlAccessorType(XmlAccessType.FIELD)public classClassA {private intclassAId;

@XmlElement(name="ClassAName")privateString classAName;privateClassB classB;public intgetClassAId() {returnclassAId;

}public void setClassAId(intclassAId) {this.classAId =classAId;

}publicString getClassAName() {returnclassAName;

}public voidsetClassAName(String classAName) {this.classAName =classAName;

}publicClassB getClassB() {returnclassB;

}public voidsetClassB(ClassB classB) {this.classB =classB;

}

}View Code

序列化结果如下,可以看到已经按照我们所预期的修改了命名空间前缀,[email protected]ootElement(namespace="http://www.lzrabbit.cn")注解时指定的namespace必须和package-info.java定义的前缀一致,否则还是会生成nsXX这样的前缀

69c5a8ac3fa60e0848d784a6dd461da6.png<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

11

A1

22

B2

69c5a8ac3fa60e0848d784a6dd461da6.png

注意事项

1.若jdk版本为1.6的需要需要添加jaxb-core-2.2.7.jar和jaxb-impl-2.2.7.jar两个包的引用,否则即便设置了package-info的XmlSchema注解的xmlns注释也不能生效,若为jdk

1.7的无需添加

2.使用XmlSchema定义的前缀会对整个包生效,无法实现对每个实体类的单独前缀定义,很不灵活,故此不推荐使用此方式

解决方法二(推荐):

同方法一若jdk版本为1.6需要添加jaxb-core-2.2.7.jar和jaxb-impl-2.2.7.jar两个包的引用,不过方法二不需要添加package-info当然也就不需要定义XmlSchema

思路就是实现NamespacePrefixMapper抽象类,并重写getPreferredPrefix方法,看到方法名应该都明白了,对就是在序列化的时候重写获取命名空间前缀方法,为了简洁这里使用类匿名内部类实现的

69c5a8ac3fa60e0848d784a6dd461da6.pngmarshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", newNamespacePrefixMapper() {

@Overridepublic String getPreferredPrefix(String namespaceUri, String suggestion, booleanrequirePrefix) {if (namespaceUri.equals("http://www.lzrabbit.cn")) return "abc";returnsuggestion;

}

});

69c5a8ac3fa60e0848d784a6dd461da6.png

如上所示,在序列化时判断namespaceUri也就是我们定义的命名空间,然后返回我们自定义的前缀,其中的suggestion参数就是默认的前缀,有兴趣的话打印下就会发现suggestion就是ns2之类的前缀,把要自定义前缀的命名空间都在这里判断下就可以完全控制自定义前缀了,相对方法一来说可以实现对每个实体类的命名空间前缀控制,采用方法二后的序列化结果:

69c5a8ac3fa60e0848d784a6dd461da6.png<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

11

A1

22

B2

69c5a8ac3fa60e0848d784a6dd461da6.png

采用方法二后的序列化方法

cdec0645add3fc3c328197dda5c76203.png

81178cc93a2a3bb5048d90d76e7ec935.png

packagecn.lzrabbit;importjava.io.StringReader;importjava.io.StringWriter;import javax.xml.bind.*;importcom.sun.xml.bind.marshaller.NamespacePrefixMapper;importcom.sun.xml.bind.v2.WellKnownNamespace;public classXmlUtil {public staticString toXML(Object obj) {try{

JAXBContext context=JAXBContext.newInstance(obj.getClass());

Marshaller marshaller=context.createMarshaller();

marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");// //编码格式

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//是否格式化生成的xml串

marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);//是否省略xm头声明信息

marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", newNamespacePrefixMapper() {

@Overridepublic String getPreferredPrefix(String namespaceUri, String suggestion, booleanrequirePrefix) {if (namespaceUri.equals("http://www.lzrabbit.cn")) return "abc";if (namespaceUri.contains("http://www.cnblogs.com")) return "blog";returnsuggestion;

}

});

StringWriter writer= newStringWriter();

marshaller.marshal(obj, writer);returnwriter.toString();

}catch(Exception e) {throw newRuntimeException(e);

}

}

@SuppressWarnings("unchecked")public static T fromXML(String xml, ClassvalueType) {try{

JAXBContext context=JAXBContext.newInstance(valueType);

Unmarshaller unmarshaller=context.createUnmarshaller();return (T) unmarshaller.unmarshal(newStringReader(xml));

}catch(Exception e) {throw newRuntimeException(e.getMessage());

}

}

}View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值