使用CDATA_SECTION_ELEMENTS编组CDATA元素会添加回车符

时间:2015-07-17 19:17:28

标签: java xml jaxb cdata line-endings

我正在处理从/向数据库导出和导入数据的应用程序。数据提取的格式是XML,我使用JAXB进行序列化/(非)编组。我希望将一些元素作为CDATA元素进行编组,并使用this solutionOutputKeys.CDATA_SECTION_ELEMENTS设置为Transformer属性。

到目前为止,这工作得很好,但是现在我来到DB中的一个字段,它本身包含一个XML字符串,我也想把它放在一个CDATA元素中。现在,由于某种原因,Transformer现在向每个行结尾添加了一些不必要的回车字符(\r),因此输出如下所示: enter image description here

这是我的代码:

  private static final String IDENT_LENGTH = "3";
  private static final String CDATA_XML_ELEMENTS = "text definition note expression mandatoryExpression optionalExpression settingsXml";

  public static void marshall(final Object rootObject, final Schema schema, final Writer writer) throws Exception {
    final JAXBContext ctx = JAXBContext.newInstance(rootObject.getClass());
    final Document document = createDocument();
    final Marshaller marshaller = ctx.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.setSchema(schema);
    marshaller.marshal(rootObject, document);
    createTransformer().transform(new DOMSource(document), new StreamResult(writer));
  }

  private static Document createDocument() throws ParserConfigurationException {
    // the DocumentBuilderFactory is actually being hold in a singleton
    final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    return builderFactory.newDocumentBuilder().newDocument();
  }

  private static Transformer createTransformer() throws TransformerConfigurationException, TransformerFactoryConfigurationError {
    // the TransformerFactory is actually being hold in a singleton
    final TransformerFactory transformerFactory = TransformerFactory.newInstance();
    final Transformer transformer = transformerFactory.newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
    transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, CDATA_XML_ELEMENTS);
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", IDENT_LENGTH);
    return transformer;
  }

我已将FileWriter传递给marshall方法。

我的带注释的模型类看起来像这样:

@XmlType
@XmlRootElement
public class DashboardSettings {

  @XmlElement
  private String settingsXml;

  public String getSettingsXml() {
    return settingsXml;
  }

  public void setSettingsXml(final String settingsXml) {
    this.settingsXml = settingsXml;
  }
}

注意:

来自数据库的XML字符串具有Windows样式行结尾,即\r\n。我觉得JAXB期望当前的Linux样式输入(即仅\n)并因此添加\r字符,因为我目前正在Windows机器上运行。所以问题实际上是,解决这个问题的最佳方法是什么?在编组时是否可以传递任何参数来控制行结束字符?或者我应该先将线路结尾转换为Linux风格的编组?我的程序将如何在不同平台(Windows,Linux,Mac OS)上运行?

我不一定需要一个独立于平台的解决方案,如果输出是Windows,Linux或任何风格,那就没关系。我想要避免的是组合\r\r\n,如上面的屏幕截图所示。

1 个答案:

答案 0 :(得分:0)

我意识到这个问题已经很老了,但是我遇到了类似的问题,所以也许答案可以帮助别人。

这似乎与CDATA部分有关。就我而言,我使用的是createCDATASection方法来创建它们。如在您的示例中那样,当代码在Windows计算机上运行时,添加了另外的CR

我已经尝试了很多方法来“干净”地解决此问题,但无济于事。

在我的项目中,然后将XML文档导出为字符串,然后将其发布到Linux服务器。因此,一旦生成了字符串,我就删除了CR个字符,只留下了LF

myXmlString.replaceAll("\\r", "");

对于特定的问题,我可能不是一个合适的解决方案,但再次,它可以帮助您(或其他人)找到解决方案。

注意:对于该特定项目,我坚持使用Java 7,因此它可能已在最新版本中得到修复。