【问题标题】:Should indenting XML in Java respect `xml:space="preserve"`?在 Java 中缩进 XML 是否应该尊重 `xml:space="preserve"`?
【发布时间】:2013-06-11 20:23:48
【问题描述】:

我正在用 Java 美化/缩进一些 XML:

<div xml:space="default"><h1 xml:space="default">Indenting mixed content in Java</h1><p xml:space="preserve">Why does indenting mixed content (like this paragraph) add whitespace around <a href="http://www.stackoverflow.com" xml:space="preserve"><strong>this strong element</strong></a>?</p></div>

当我美化 XML 时,我不希望将空格添加到 &lt;a&gt; 元素的内容中,因此我指定了 xml:space="preserve" 期望转换器保留其中的空格。

但是,当我转换 XML 时,我得到了这个:

<div>
    <h1 xml:space="default">Indenting mixed content in Java</h1>
    <p>Why does indenting mixed content (like this paragraph) add whitespace around <a href="http://www.stackoverflow.com">
            <strong xml:space="preserve">this strong element</strong>
        </a>?</p>
</div>

...在&lt;a&gt; 和&lt;strong&gt; 元素之间有额外的空格。 (不仅如此,&lt;/a&gt; 关闭标签尴尬地不与它的打开标签对齐。)

如何防止美化者添加该空白?难道我做错了什么?这是我正在使用的 Java 代码:

import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import java.io.ByteArrayInputStream;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import java.io.StringWriter;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.stream.StreamResult;

public class XmlExample {

    public static void main(String[] argv) {
        Document xmlDoc    = parseXml("<div xml:space=\"default\">" + 
                                          "<h1 xml:space=\"default\">Indenting mixed content in Java</h1>" + 
                                          "<p xml:space=\"preserve\">Why does indenting mixed content (like this paragraph) add whitespace around " + 
                                              "<a href=\"http://www.stackoverflow.com\" xml:space=\"preserve\"><strong>this strong element</strong></a>?" + 
                                          "</p>" + 
                                      "</div>");
        String   xmlString = xmlToString(xmlDoc.getDocumentElement());
        System.out.println(xmlString);
    }

    public static Document parseXml(String xml) {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            docFactory.setNamespaceAware(true);
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

            Document doc = docBuilder.parse(new ByteArrayInputStream(xml.getBytes("UTF-8"))); 
            return doc;
        }
        catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String xmlToString(Element el) {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            DOMSource source = new DOMSource(el);
            transformer.transform(source, new StreamResult(writer));
            return writer.getBuffer().toString().trim();
        }
        catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

【问题讨论】:

  • 我无法明确回答您的问题 - 您正在处理混合内容,缩进规则可能取决于处理器。可能值得尝试另一个 XSLT 引擎,例如 Saxon。这是关于空格的另一个 SO 问题stackoverflow.com/questions/1384802/…
  • @peter.murray.rust - 是的,这个问题和我最近成为了非常要好的朋友:P 不过我会调查一下撒克逊人。
  • 我可能最信任撒克逊人。 Mike Kay 帮助创建了规范,并将在此类事情上非常彻底。他可能会给你一个直接的答案。

标签: java xml pretty-print


【解决方案1】:

如果您使用符合 XSLT 1.0 或 XSLT 2.0 规范的序列化程序,那么它应该尊重 xml:space(即,在 xml:space="preserve" 的范围内,应该禁止缩进)。 XSLT 2.0 规范在这一点上比 XSLT 1.0 更明确,并使其成为“必须”而不是“应该”要求。

您使用的是 JAXP 身份转换而不是 XSLT 转换; JAXP 规范中有对 XSLT 1.0 规范的引用,但它有点模糊。

如果你使用 Saxon,你应该得到想要的行为。 Saxon 还允许您使用 SUPPRESS_INDENTATION 输出参数抑制特定元素的缩进,因此您甚至不必在被序列化的文档中包含 xml:space。

【讨论】:

  • +1 我记得很多关于空格的讨论,正如你所说,我怀疑它在 1.0 版本中并未得到一致理解或实施。
猜你喜欢
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
相关资源
最近更新 更多