4

要温柔。

我正在尝试使用 javax.xml.transform.Transformer 格式化一些 xml 字符串以在标签之间缩进/无空格。如果标签之间没有空格,则可以正常工作。如果有它的行为很奇怪。我会发布一个例子。我试图跟进以下主题: http://forums.sun.com/thread.jspa?messageID= 2054303#2699961。没有成功。

要遵循的代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
   factory.setIgnoringElementContentWhitespace(true);
   DocumentBuilder builder = factory.newDocumentBuilder();
   DOMImplementation domImpl = builder.getDOMImplementation();
   DOMImplementationLS ls = (DOMImplementationLS) domImpl.getFeature("LS", "3.0");
   LSInput in = ls.createLSInput();
   in.setByteStream(new ByteArrayInputStream(input.getBytes()));
   LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS,
     "http://www.w3.org/2001/XMLSchema");
   Document xmlInput = parser.parse(in);

   StringWriter stringWriter = new StringWriter();
   StreamResult xmlOutput = new StreamResult(stringWriter);
   TransformerFactory f = TransformerFactory.newInstance();
   f.setAttribute("indent-number", 2);

   Transformer transformer = f.newTransformer();
   transformer.setOutputProperty(OutputKeys.INDENT, "yes");
   transformer.setOutputProperty(OutputKeys.METHOD, "xml");
   transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
   transformer.transform(new DOMSource(xmlInput), xmlOutput);

如果标签之间没有中断

input : <tag><nested>    hello   </nested></tag>
output : 
<tag>
  <nested>    hello   </nested>
</tag>

如果有 :

input : <tag>  <nested>    hello   </nested></tag>
output : 
<tag>  <nested>    hello   </nested>
</tag>

JVM 1.6。

这里有什么明显的错误吗?

4

2 回答 2

3

这一定是变压器实现的问题。我创建了一个小型测试类,它读取没有空格或换行符的字符串作为 XML,并从 XSLT 样式表(也从字符串)创建转换器。样式表指定缩进必须发生。这基本上是实现你所做的事情的另一种方式transformer.setOutputProperty(OutputKeys.INDENT, "yes");

这里是:

package transformation;

import java.io.StringReader;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class TransformerTest {

    public static void main(String[] args) throws Exception {

        final String xmlSample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag><nested>hello</nested></tag>";
        final String stylesheet = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"xml\" version=\"1.0\" indent=\"yes\"/><xsl:template match=\"node()|@*\"><xsl:copy><xsl:apply-templates select=\"node()|@*\"/></xsl:copy></xsl:template></xsl:stylesheet>";

        final TransformerFactory factory = TransformerFactory.newInstance();

        final Source xslSource = new StreamSource(new StringReader(stylesheet));
        final Transformer transformer = factory.newTransformer(xslSource);

        final Source source = new StreamSource(new StringReader(xmlSample));
        final Result result = new StreamResult(System.out);

        transformer.transform(source, result);

    }

}

现在奇怪的是,结果因我使用的变压器而异。如果我没有在类路径上放置任何 TransformerFactory 实现(使用 JRE 库中的默认实现),结果是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<tag>
<nested>hello</nested>
</tag>

不正确,因为标签没有缩进。

然后,通过在类路径上添加最近的 Xalan 实现(xalan.jar 和 serializer.jar,仍然使用 JRE 默认解析器/DOM 构建器),我得到了:

<?xml version="1.0" encoding="UTF-8"?><tag>
<nested>hello</nested>
</tag>

仍然不正确,第一个标记与 XML 声明在同一行并且没有缩进。

老实说,这让我很震惊。我会理解标签之间或文本节点周围的空格是否会影响缩进,因为转换器可能会假设其中一些是不可忽略的。但是看到一个像这样被破坏的简单的 XML 是很奇怪的。我想也许使用控制台输出可能与它有关,所以我尝试流式传输到文件。结果相同。

有点奇怪,长期存在的变压器实现仍然具有这种行为。但并不像我注意到使用模式验证器导致属性从“增强的”XML 输出中删除时那么糟糕。

因此,除了尝试找到其他处理器并查看它们是否有同样的问题之外,似乎没有什么可做的。也许撒克逊人值得一试。这个错误报告也很有趣(但是它适用于 Java 1.5): http ://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

于 2011-03-04T19:40:26.830 回答
0

变压器似乎不喜欢空白,所以最简单的解决方案似乎是简单地删除它....

    public String prettyPrintXML(String inXML)  {

       String outXML = inXML;

// The transformer doesn't like white space between tags so remove it.          
           String[] bits = inXML.split(">");      
       inXML="";
       boolean first = true;
       for (int n=0;n<bits.length; n++){
           if (first)
            inXML = inXML + bits[n].trim();
           else
             inXML = inXML + ">"+bits[n].trim();

           first = false;
       }
      inXML = inXML + ">";

将 inXML 传递到您的转换器中,然后您就可以离开了。

于 2015-05-06T09:20:45.163 回答