【问题标题】:How to preserve newlines in CDATA when generating XML?生成 XML 时如何在 CDATA 中保留换行符?
【发布时间】:2010-11-16 01:21:10
【问题描述】:

我想将一些包含空格字符的文本(例如 newlinetab)写入 xml 文件,所以我使用

Element element = xmldoc.createElement("TestElement");
element.appendChild(xmldoc.createCDATASection(somestring));

但是当我在使用中读回这篇文章时

Node vs =  xmldoc.getElementsByTagName("TestElement").item(0);
String x = vs.getFirstChild().getNodeValue();

我得到一个不再有换行符的字符串。
当我直接查看磁盘上的 xml 时,似乎保留了换行符。所以在读取xml文件时会出现问题。

如何保留换行符?

谢谢!

【问题讨论】:

  • 你能发布一个更完整的代码示例吗?
  • 它是一个元素。我会尽快发布更多代码。
  • 当你得到'x'的值时,它相当于'somestring'减去换行符?
  • 您是否尝试过将\n 上的反斜杠转义为\\n
  • 正在使用什么换行符?在黑暗中拍摄,但我想知道它是否与如何支持换行符有关:w3.org/TR/REC-xml/#sec-line-ends

标签: java xml newline w3c cdata


【解决方案1】:

xml:space='preserve' 是不是。这仅适用于“所有空白”节点。也就是说,如果你想要

中的空白节点
<this xml:space='preserve'> <has/>
<whitespace/>
</this>

但是请注意,那些空白节点只是空白。

我一直在努力让 Xerces 生成允许隔离 CDATA 内容的事件。我还没有解决办法。

【讨论】:

    【解决方案2】:

    我不知道您是如何解析和编写文档的,但这里有一个基于您的增强代码示例:

    // creating the document in-memory                                                        
    Document xmldoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    
    Element element = xmldoc.createElement("TestElement");                                    
    xmldoc.appendChild(element);                                                              
    element.appendChild(xmldoc.createCDATASection("first line\nsecond line\n"));              
    
    // serializing the xml to a string                                                        
    DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();             
    
    DOMImplementationLS impl =                                                                
        (DOMImplementationLS)registry.getDOMImplementation("LS");                             
    
    LSSerializer writer = impl.createLSSerializer();                                          
    String str = writer.writeToString(xmldoc);                                                
    
    // printing the xml for verification of whitespace in cdata                               
    System.out.println("--- XML ---");                                                        
    System.out.println(str);                                                                  
    
    // de-serializing the xml from the string                                                 
    final Charset charset = Charset.forName("utf-16");                                        
    final ByteArrayInputStream input = new ByteArrayInputStream(str.getBytes(charset));       
    Document xmldoc2 = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input);
    
    Node vs =  xmldoc2.getElementsByTagName("TestElement").item(0);                           
    final Node child = vs.getFirstChild();                                                    
    String x = child.getNodeValue();                                                          
    
    // print the value, yay!                                                                  
    System.out.println("--- Node Text ---");                                                  
    System.out.println(x);                                                                    
    

    使用 LSSerializer 的序列化是 W3C 的实现方式 (see here)。输出符合预期,带有行分隔符:

    --- XML --- 
    <?xml version="1.0" encoding="UTF-16"?>
    <TestElement><![CDATA[first line
    second line ]]></TestElement>
    --- Node Text --- 
    first line
    second line
    

    【讨论】:

    • 谢谢,我试过了,但对我不起作用。虽然我可以在磁盘上的 xmlfile 中看到换行符,但一旦我用这段代码读回它们,它们就消失了。也许我的换行符不好。我怎样才能知道它是哪一个?
    • 我展示的输出是我发布的代码示例的真实输出。您是否尝试使用我建议的代码编写文本?还是只使用我的代码阅读它?此外,您的文件的编码是什么(您可以在我的示例中看到,编码是 UTF-16)。由于不使用相同的编码,我遇到了类似的问题,我通过使用 Charset.forName() 和实际使用的编码来修复它。
    • 是的,我确实尝试过你的实际代码。我使用完全相同的代码来输出字​​符串。但它不包含空格。我使用的编码是 encoding="ISO-8859-1" 我会尝试使用 UTF-16
    • 如果您使用与 ISO-8859-1 完全相同的代码,您将遇到问题 - 除非您将 Charset.forName 更改为使用 ISO-8859-1。 ASCII 和 UTF-16 之间的换行可能会出现问题,因此值得一试。
    • 我在反序列化时尝试使用“utf-16”,但在我的情况下..它正在将“\r\n”转换为“\n\n”,这给我带来了问题。你能提供这个问题的解决方案吗?
    【解决方案3】:

    编辑:删除所有不相关的东西

    我很想知道您使用的是什么 DOM 实现,因为它没有反映我尝试过的几个 JVM 中的默认行为(它们附带 Xerces impl)。我也对您的文档有哪些换行符感兴趣。

    我不确定 CDATA 是否应该保留空格是给定的。我怀疑这涉及到很多因素。 DTD/模式不会影响空格的处理方式吗?

    您可以尝试使用 xml:space="preserve" 属性。

    【讨论】:

    • 谢谢,我应该在哪里添加 xml:space="preserve" 属性?到包含文本的节点还是到 xml 根?
    【解决方案4】:

    您不一定必须使用 CDATA 来保留空白字符。 XML specification 指定如何编码这些字符。

    因此,例如,如果您的元素的值包含新空间,则应使用

    对其进行编码
      &#xA;
    

    回车:

     &#xD;
    

    等等

    【讨论】:

    • 谢谢,但有没有不编码的方法?这样我就可以在 xml 文件本身中看到格式化的文本?
    【解决方案5】:

    您需要使用 node.getNodeType() 检查每个节点的类型。如果类型是 CDATA_SECTION_NODE,则需要将 CDATA 守卫连接到 node.getNodeValue。

    【讨论】:

    • 是的,节点的类型是CDATA。但是你对 concat CDATA 守卫是什么意思?
    猜你喜欢
    • 1970-01-01
    • 2011-05-25
    • 2013-03-19
    • 2011-03-24
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多