我正在尝试使用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。
这里有明显的错误吗?
答案 0 :(得分: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就像那个被破坏的那样简直就是奇怪了。我想也许使用控制台输出可能与它有关,所以我尝试流式传输到文件。结果相同。奇怪的是,长期以来的变压器实现仍然存在这样的行为。但是,当我注意到使用Schema的Validator导致属性从“增强的”XML输出中删除时,并没有那么糟糕。
除了试图寻找其他处理器并看看它们是否遇到同样的问题之外,似乎没有太多可以做的事情。也许萨克森值得一试。这个错误报告也很有趣(但它适用于Java 1.5): http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446
答案 1 :(得分: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传递到您的变压器中然后离开。