JAXB控制CDATA节点转义

来源:互联网 发布:java编程实战案例 编辑:程序博客网 时间:2024/05/29 16:50

参看:http://liugang594.iteye.com/blog/1981726

参看:http://blog.csdn.net/qustmeng/article/details/53706657


       在使用JAXB,将对象转换成xml时,有时会遇到节点需要包含<![CDATA[...]]>的情况,至于为什么要加<![CDATA[..]]>,这里就不再详述了。今天讨论在使用JAXB时,如何使对象属性值在转换到xml文件中时,会用<![CDATA[..]>包装。

       特别说明,本方法并不是唯一的解决该问题的方法。

       第一步:实现自定义的XmlAdaper<String, Stirng>, 比例自定义的类名为CDATASectionAdapter,CDATASectionAdapter的作用就是在写到xml文件之前,为属性值添加上“<![CDATA[ ]]>”。实现代码如下:

public class CDATASectionAdapter extends XmlAdapter<String, String> {        @Override      public String unmarshal(String v) throws Exception {          return v;      }        @Override      public String marshal(String v) throws Exception {          if(v != null){              return "<![CDATA["+v+"]]>";          }          return null;      }    }  

    第二步,为需要加CDATA标记的类属性添加@XmlJavaTypeAdapter注解,该注解的作用就是标记该属性在转换到xml中或从xml中解析时,调用一个Adapter类的方法,这个Adapter就是指我们上面实现的CDATASectionAdapter类,具体写法示例:

@XmlElement(name="name")  @XmlJavaTypeAdapter(CDATASectionAdapter.class)  protected String name;
    注:上述代码,就是让属性name,在转换时调用CDATASectionAdapter类中的转换方法。因此,这样就可以为name属性值包装上“<![CDATA[ ..]]>”。


    至此,输出的xml文件中name属性已经被加上了CDATA的包装,只是“<”和“>”会被转义,"<"被转义为“&lt;”, ">"被转义为"&gt;",所以xml中的显示结果可能为:

<name><&lt;![CDATA[Bob]]&gt;</name>  

    因此,我们要消除转义,换句话说,就是阻止JAXB进行的转义动作。这就是第三步的任务。

   第三步,实现自定义的CharacterEscapeHandler类,拦截JAXB的转义动作。(由于该类过于简单,没必要创建新的文件,直接定义成匿名内部类,如第四步示例所示)

   第四步,在将对象转换成xml时,会用到Marshaller对象,调用该对象的setProperty方法,注入第三步中实现的类,控制转换时不进行转义,例如:

try {      JAXBContext context = JAXBContext.newInstance(obj.getClass());      Marshaller marshaller = context.createMarshaller();      // xml格式      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);         // 不进行转义字符的处理      marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {             public void escape(char[] ch, int start,int length, boolean isAttVal, Writer writer) throws IOException {                 writer.write(ch, start, length);             }           });      StringWriter sw = new StringWriter();  marshaller.marshal(obj, sw);      return sw.toString();  } catch (JAXBException e) {      log.error("", e);  }
注:上述代码中用到的CharacterEscapeHandler类是CharacterEscapeHandler为com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler。

注:所谓的拦截,就是上述匿名内部类重载的escape方法,不做其他动作,只是将输入参数传递到writer中。




原创粉丝点击