XStream双下划线问题解决与CDATA标记同时的方案

简介: <div class="markdown_views"><h2 id="1问题">1、问题</h2><p>在微信开发过程中,需要进行xml格式的数据传输。有些微信接口的xml数据中需要加上CDATA标记,而大部分的xml数据的标签名都带有下划线。注意,微信接口中的数据是有下划线的,是“_”不是“-”,让我很郁闷。</p><h2 id="2使用xstream把java对

1、问题

在微信开发过程中,需要进行xml格式的数据传输。有些微信接口的xml数据中需要加上CDATA标记,而大部分的xml数据的标签名都带有下划线。注意,微信接口中的数据是有下划线的,是“_”不是“-”,让我很郁闷。

2、使用XStream把Java对象转成xml格式的数据

            UnifiedOrder unifiedOrder = new UnifiedOrder();
            unifiedOrder.setAppid("123456");
            unifiedOrder.setAttach("hehedesk");
            unifiedOrder.setBody("hehedesk");
            unifiedOrder.setOpenid("5654675");
            unifiedOrder.setSign("0000000000000000");
            XStream stream = new XStream();
            stream.alias("xml", unifiedOrder.getClass());
            String xml = stream.toXML(unifiedOrder);
            System.out.println(xml);

输出XML为:

<xml>
  <appid>123456</appid>
  <attach>hehedesk</attach>
  <body>hehedesk</body>
  <openid>5654675</openid>
  <sign>0000000000000000</sign>
</xml>

3、为数据加上CDATA标记

修改XStream的实现就可以。

        XStream stream = new XStream(new XppDriver(new NoNameCoder()) {

                @Override
                public HierarchicalStreamWriter createWriter(Writer out) {
                    return new PrettyPrintWriter(out) {
                        // 对所有xml节点的转换都增加CDATA标记
                        boolean cdata = true;

                        @Override
                        @SuppressWarnings("rawtypes")
                        public void startNode(String name, Class clazz) {
                            super.startNode(name, clazz);
                        }

                        @Override
                        protected void writeText(QuickWriter writer, String text) {
                            if (cdata) {
                                writer.write("<![CDATA[");
                                writer.write(text);
                                writer.write("]]>");
                            } else {
                                writer.write(text);
                            }
                        }
                    };
                }
            });

输出XML为:

<xml>
  <appid><![CDATA[123456]]></appid>
  <attach><![CDATA[hehedesk]]></attach>
  <body><![CDATA[hehedesk]]></body>
  <openid><![CDATA[5654675]]></openid>
  <sign><![CDATA[0000000000000000]]></sign>
</xml>

4、当对象属性带下划线时,XStream转换成双下划线

            UnifiedOrder unifiedOrder = new UnifiedOrder();
            unifiedOrder.setAppid("123456");
            unifiedOrder.setAttach("hehedesk");
            unifiedOrder.setBody("hehedesk");
            unifiedOrder.setOpenid("5654675");
            unifiedOrder.setSign("0000000000000000");
            unifiedOrder.setMch_id("123456");
            XStream stream = new XStream();
            stream.alias("xml", unifiedOrder.getClass());
            String xml = stream.toXML(unifiedOrder);

输出XML:

<xml>
  <appid>123456</appid>
  <mch__id>123456</mch__id>
  <attach>hehedesk</attach>
  <body>hehedesk</body>
  <openid>5654675</openid>
  <sign>0000000000000000</sign>
</xml>

注意:这里mch_id的下线线由XStream转成了”__”。

度娘上找到的解决方法:

new DomDriver(null,new XmlFriendlyNameCoder("_-", "_"))

经过测试,XmlFriendlyNameCoder与XppDriver不能同时存在。so,问题来了。如何才能让两者共存呢。

5、双下划线问题解决与CDATA标记同时的方案

双下划线问题的产生是因为XStream默认的转换方式中定义了对特殊字符的转换,代码如下:

//XmlFriendlyNameCoder.encodeName(String name)
for (; i < length; i++ ) {
            char c = name.charAt(i);
            if (c == '$' || c == '_' || c <= 27 || c >= 127) {
                break;
            }
 }

也就是说,我们在转换的过程中,不对特殊字符进行转换就可以了。

XppDriver类中有对字符转换的方法:

    /**
     * Encode the node name into the name of the target format.
     * 
     * @param name the original name
     * @return the name in the target format
     * @since 1.4
     */
    public String encodeNode(String name) {
        return nameCoder.encodeNode(name);
    }

这里可以看到,XppDriver的encodeNode是把节点的名称进行格式化。然后调用nameCoder对象对名字进行编译。

我们在XppDriver的子类中,重写此方法,不再像XppDriver那样调用nameCoder来进行编译,而是直接返回节点名称。

@Override
public String encodeNode(String name) {
    return name;
}

完整代码如下:

            XStream stream = new XStream(new XppDriver(new NoNameCoder()) {

                @Override
                public HierarchicalStreamWriter createWriter(Writer out) {
                    return new PrettyPrintWriter(out) {
                        // 对所有xml节点的转换都增加CDATA标记
                        boolean cdata = true;

                        @Override
                        @SuppressWarnings("rawtypes")
                        public void startNode(String name, Class clazz) {
                            super.startNode(name, clazz);
                        }

                        @Override
                        public String encodeNode(String name) {
                            return name;
                        }


                        @Override
                        protected void writeText(QuickWriter writer, String text) {
                            if (cdata) {
                                writer.write("<![CDATA[");
                                writer.write(text);
                                writer.write("]]>");
                            } else {
                                writer.write(text);
                            }
                        }
                    };
                }
            });

输出XML:

<xml>
  <appid><![CDATA[123456]]></appid>
  <mch_id><![CDATA[1111111]]></mch_id>
  <attach><![CDATA[hehedesk]]></attach>
  <body><![CDATA[hehedesk]]></body>
  <openid><![CDATA[5654675]]></openid>
  <trade_type><![CDATA[JSAPI]]></trade_type>
  <sign><![CDATA[0000000000000000]]></sign>
  <device_info><![CDATA[WEB]]></device_info>
</xml>
目录
相关文章
|
fastjson 前端开发
巧用fastjson自定义序列化类实现字段的转换
项目中突然需要增加另一个字段的查找,而这个查找需要查另一张表的记录。 但现在产品很多地方都要增加该字段,如何最快的实现该功能呢。 办法如下: 通过fastjson序列化时,增加该字段的序列化类,该序列化类通过CODE查找名称,并序列化到前端。
5859 0
|
4月前
|
存储 Java
java的Excel导出,数组与业务字典匹配并去掉最后一个逗号
java的Excel导出,数组与业务字典匹配并去掉最后一个逗号
74 2
|
Java 数据库连接 mybatis
mybatis异常 :元素内容必须由格式正确的字符数据或标记组成。
今天同事写一个查询接口的时候,出错:元素内容必须由格式正确的字符数据或标记组成。   错误原因:mybatis查询的时候,需要用到运算符 小于号:< 和  大于号: >,在mybatis配置文件里面,这种会被认为是标签,所以解析错误 错误事例: select from t...
1861 0
|
8月前
|
XML SQL Java
MyBatis【付诸实践 01】mapper.xml 中特殊符号的 2 种处理方法(CDATA区+替代字符举例)
MyBatis【付诸实践 01】mapper.xml 中特殊符号的 2 种处理方法(CDATA区+替代字符举例)
290 0
|
8月前
|
Oracle Java 关系型数据库
Java【代码分享 06】Lamda表达式将List对象中的Map对象的key全部转化为大写或者小写(去除外层循环:可用于Map对象中的key全部转化为大写或者小写)
Java【代码分享 06】Lamda表达式将List对象中的Map对象的key全部转化为大写或者小写(去除外层循环:可用于Map对象中的key全部转化为大写或者小写)
371 0
|
JSON 前端开发 Java
springboot中自定义JavaBean返回的json对象属性名称大写变小写问题
springboot中自定义JavaBean返回的json对象属性名称大写变小写问题
232 0
|
XML 数据格式
使用XStream进行对象和xml的转换,极度舒适
使用XStream进行对象和xml的转换,极度舒适
167 0
|
XML 前端开发 Java
XStream(可把javabean转换成XMI的小工具)|学习笔记
快速学习XStream(可把javabean转换成XMI的小工具)
|
XML 数据格式
记一次思路:如何取消JDOM生成xml时的自动转义
记一次思路:如何取消JDOM生成xml时的自动转义
记一次思路:如何取消JDOM生成xml时的自动转义
|
XML Java 数据格式
XStream转换器: 处理xml节点中既有属性又有值
XStream转换器: 处理xml节点中既有属性又有值
673 0