首页 > 编程 > Java > 正文

JAXB命名空间及前缀_动力节点Java学院整理

2019-11-26 11:35:39
字体:
来源:转载
供稿:网友

本文讲解使用jaxb结合dom4j的XMLFilterImpl过滤器实现序列化和反序列化的完全控制

主要实现以下功能

  • 序列化及反序列化时忽略命名空间
  • 序列化时使用@XmlRootElement(namespace="http://www.lzrabbit.cn")注解作为类的默认命名空间,彻底消除命名空间前缀
  • 序列化时引用类有不同命名空间时也不会生成命名空间前缀,而是在具体的xml节点上添加相应的xmlns声明
  • 其它的xml节点命名及命名空间需求
  • 同一个包下有多个命名空间
  • 自定义命名空间前缀

依赖的jar dom4j

 <dependency>   <groupId>dom4j</groupId>   <artifactId>dom4j</artifactId>   <version>1.6.1</version> </dependency>

主要原理就是在序列化和反序列化时通过XMLFilterImpl的匿名实现类实现命名空间及xml节点名称的控制,实现多样化需求,废话不多说直接上代码,有更多个性化需求的看官请自行扩展

package com.bjpowernode.util;import java.io.StringReader;import java.io.StringWriter;import javax.xml.bind.*;import javax.xml.transform.sax.SAXSource;import org.dom4j.io.OutputFormat;import org.dom4j.io.XMLWriter;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.XMLFilterImpl;import org.xml.sax.helpers.XMLReaderFactory;public class XmlUtil { public static String 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头声明信息   StringWriter out = new StringWriter();   OutputFormat format = new OutputFormat();   format.setIndent(true);   format.setNewlines(true);   format.setNewLineAfterDeclaration(false);   XMLWriter writer = new XMLWriter(out, format);   XMLFilterImpl nsfFilter = new XMLFilterImpl() {    private boolean ignoreNamespace = false;    private String rootNamespace = null;    private boolean isRootElement = true;    @Override    public void startDocument() throws SAXException {     super.startDocument();    }    @Override    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {     if (this.ignoreNamespace) uri = "";     if (this.isRootElement) this.isRootElement = false;     else if (!uri.equals("") && !localName.contains("xmlns")) localName = localName + " xmlns=/"" + uri + "/"";     super.startElement(uri, localName, localName, atts);    }    @Override    public void endElement(String uri, String localName, String qName) throws SAXException {     if (this.ignoreNamespace) uri = "";     super.endElement(uri, localName, localName);    }    @Override    public void startPrefixMapping(String prefix, String url) throws SAXException {     if (this.rootNamespace != null) url = this.rootNamespace;     if (!this.ignoreNamespace) super.startPrefixMapping("", url);    }   };   nsfFilter.setContentHandler(writer);   marshaller.marshal(obj, nsfFilter);   return out.toString();  } catch (Exception e) {   throw new RuntimeException(e);  } } public static <T> T fromXML(String xml, Class<T> valueType) {  try {   JAXBContext context = JAXBContext.newInstance(valueType);   Unmarshaller unmarshaller = context.createUnmarshaller();   // return (T) unmarshaller.unmarshal(new StringReader(xml));   SerializeUtil obj = new SerializeUtil();   XMLReader reader = XMLReaderFactory.createXMLReader();   XMLFilterImpl nsfFilter = new XMLFilterImpl() {    private boolean ignoreNamespace = false;    @Override    public void startDocument() throws SAXException {     super.startDocument();    }    @Override    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {     if (this.ignoreNamespace) uri = "";     super.startElement(uri, localName, qName, atts);    }    @Override    public void endElement(String uri, String localName, String qName) throws SAXException {     if (this.ignoreNamespace) uri = "";     super.endElement(uri, localName, localName);    }    @Override    public void startPrefixMapping(String prefix, String url) throws SAXException {     if (!this.ignoreNamespace) super.startPrefixMapping("", url);    }   };   nsfFilter.setParent(reader);   InputSource input = new InputSource(new StringReader(xml));   SAXSource source = new SAXSource(nsfFilter, input);   return (T) unmarshaller.unmarshal(source);  } catch (Exception e) {   throw new RuntimeException(e.getMessage());  } }}

示例实体类

import javax.xml.bind.annotation.*;@XmlRootElement(namespace="http://www.lzrabbit.cn/")@XmlAccessorType(XmlAccessType.FIELD)public class ClassA { private int classAId;  @XmlElement(name="ClassAName") private String classAName; @XmlElement(namespace="http://www.cnblogs.com/") private ClassB classB; public int getClassAId() {  return classAId; } public void setClassAId(int classAId) {  this.classAId = classAId; } public String getClassAName() {  return classAName; } public void setClassAName(String classAName) {  this.classAName = classAName; } public ClassB getClassB() {  return classB; } public void setClassB(ClassB classB) {  this.classB = classB; }}import javax.xml.bind.annotation.*;@XmlAccessorType(XmlAccessType.FIELD)public class ClassB { private int ClassBId; private String ClassBName; public int getClassBId() {  return ClassBId; } public void setClassBId(int classBId) {  this.ClassBId = classBId; } public String getClassBName() {  return ClassBName; } public void setClassBName(String classBName) {  this.ClassBName = classBName; }}

调用

import com.bjpowernode.util.XmlUtil;public class MainRun { /**  * @param args  */ public static void main(String[] args) {  ClassB classB = new ClassB();  classB.setClassBId(22);  classB.setClassBName("B2");  ClassA classA = new ClassA();  classA.setClassAId(11);  classA.setClassAName("A1");  classA.setClassB(classB);  System.out.println(XmlUtil.toXML(classA)); }}

输出结果:

<?xml version="1.0" encoding="UTF-8"?><classA xmlns="http://www.lzrabbit.cn/"> <classAId>11</classAId> <ClassAName>A1</ClassAName> <classB xmlns="http://www.cnblogs.com/"> <ClassBId>22</ClassBId> <ClassBName>B2</ClassBName> </classB></classA>

可以看到输出的xml完全达到我们的预期

实现细节都在代码里面了,很简单,当遇到有特殊需求的xml命名空间问题时,再也不用愁了

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对武林网的支持。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表