【问题标题】:Handling XML escape characters (e.g. quotes) using JAXB Marshaller使用 JAXB Marshaller 处理 XML 转义字符(例如引号)
【发布时间】:2011-05-25 01:41:11
【问题描述】:

我需要使用 JAXB Marshaller(JAXB 版本 2.2)将 XML java 对象序列化为 XML 文件。现在在 xml 对象中,我有一个包含 String value 的标签,这样:

"<"tagA>
**"<"YYYYY>done"<"/YYYYY>**
"<"/tagA>

现在你可以看到这个字符串值再次包含标签。 我希望在 xml 文件中以相同的方式写入。

但是 JAXB Marshaller 会转换这些值,例如:

"&amp;"lt;YYYYY"&amp;"gt;"&amp;"#xD;done ...& 以此类推

我无法使用 JAXB 2.2 分别处理这些转义字符 到底有没有可能?

在这方面的任何帮助都会很棒..

提前致谢, 阿比纳夫·米什拉

【问题讨论】:

    标签: java jaxb escaping character marshalling


    【解决方案1】:

    您可以利用 CDATA 结构。标准 JAXB 不涵盖此结构。 EclipseLink JAXB (MOXy) 中有一个扩展名(我是技术负责人)。查看我对相关问题的回答:

    它描述了 MOXy 中的@XmlCDATA 注解:

    import javax.xml.bind.annotation.XmlRootElement;
    import org.eclipse.persistence.oxm.annotations.XmlCDATA;
    
    @XmlRootElement(name="c")
    public class Customer {
    
       private String bio;
    
       @XmlCDATA
       public void setBio(String bio) {
          this.bio = bio;
       }
    
       public String getBio() {
          return bio;
       }
    
    }
    

    欲了解更多信息,请参阅:

    【讨论】:

    • 感谢您的回复布莱斯。我肯定会探索这个,因为它看起来很有趣。但是,我找到了解决问题的方法,我将在下面发布..
    【解决方案2】:

    通过为 JAXB Marshaller 设置以下属性来完成:

    marshaller.setProperty("jaxb.encoding", "Unicode");
    

    【讨论】:

    • 能否请您详细说明一下您的用法以转义字符。我无法通过将属性设置为 unicode 来做到这一点。
    • 为了详细说明,我刚刚为编组器设置了以下属性: marshaller.setProperty("jaxb.encoding", "Unicode"); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());
    • 在第三个语句中,您可以看到我创建了一个 CustomCharacterEscapeHandler 类,它实际上是在处理转义字符。您可以通过搜索“如何覆盖 CharacterEscapeHandler 的转义方法”在网上轻松找到它的代码。如果你需要代码然后问我..
    【解决方案3】:

    根据您要寻找的内容,您可以:

    • 禁用字符转义
    • 或使用 CDATA 字符串,只需稍加配置即可将支持添加到 JAXB 中

    【讨论】:

      【解决方案4】:

      有一种更简单的方法。首先使用自定义转义序列:

      m.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() {
          @Override
          public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
              out.write( ch, start, length ); 
          }
      }); 
      

      然后将其编组为如下所述的字符串

      StringWriter writer = new StringWriter();
      m.marshal(marshalObject, writer);
      

      然后从下面提到的 writer 中创建一个文档对象

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      InputSource is = new InputSource( new StringReader( writer.toString() ) );
      Document doc = builder.parse( is );
      

      转义字符问题将得到解决

      【讨论】:

      • 这种方法的问题是你不能用 OpenJDK 构建应用程序。 com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler 属于 Sun JDK。
      • 可以使用 com.sun.xml.bind.marshaller.CharacterEscapeHandler
      • @user2814648 com.sun.xml.bind.marshaller.CharacterEscapeHandler 不在类路径中。至少,不适合我。它在哪个图书馆?
      【解决方案5】:

      使用 JAXB 编组器,如果您想完全控制要转义的字符(例如“\'”),则必须添加属性:

      Marshaller marshaller = jc.createMarshaller();
      marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler());
      

      并创建一个新的 CustomCharacterEscapeHandler 类

      import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
      
      import java.io.IOException;
      import java.io.Writer;
      
      public class CustomCharacterEscapeHandler implements CharacterEscapeHandler {
      
          public CustomCharacterEscapeHandler() {
              super();
          }
      
          public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
              // avoid calling the Writerwrite method too much by assuming
              // that the escaping occurs rarely.
              // profiling revealed that this is faster than the naive code.
              int limit = start+length;
              for (int i = start; i < limit; i++) {
                  char c = ch[i];
                  if(c == '&' || c == '<' || c == '>' || c == '\'' || (c == '\"' && isAttVal) ) {
                      if(i!=start)
                          out.write(ch,start,i-start);
                      start = i+1;
                      switch (ch[i]) {
                          case '&':
                              out.write("&amp;");
                              break;
                          case '<':
                              out.write("&lt;");
                              break;
                          case '>':
                              out.write("&gt;");
                              break;
                          case '\"':
                              out.write("&quot;");
                              break;
                          case '\'':
                              out.write("&apos;");
                              break;
                      }
                  }
              }
      
              if( start!=limit )
                  out.write(ch,start,limit-start);
          }
      }
      

      希望对您有所帮助。

      【讨论】:

      • 我认为你在 c == '\'' 中缺少 && isAttVal。
      猜你喜欢
      • 1970-01-01
      • 2015-06-14
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      相关资源
      最近更新 更多