首页 > 学院 > 开发设计 > 正文

JAXB玩转命名空间

2019-11-06 07:31:43
字体:
来源:转载
供稿:网友

声明:如果你正在发愁xml命名空间及其前缀问题,那么请继续,否则请跳过

本文讲解使用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 cn.lzrabbit.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 cn.lzrabbit.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命名空间问题时,再也不用愁了

 

注:此文章属懒惰的肥兔原创,版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接

若您觉得这篇文章还不错请点击下右下角的推荐,有了您的支持才能激发作者更大的写作热情,非常感谢。


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