我遇到了这个我似乎无法弄清楚的奇怪问题。到目前为止,我的转换方法似乎几乎完美无缺,但我目前正在构建的工具让我有些头疼。
这是我的方法:
这个可以正常工作并生成正确的 XML
public static void transform(String filename, String filePath, String stylesheetPath, String outputTo, boolean prettyPrint, boolean excludeDeclaration) throws TransformerException, IOException {
if (!new File(outputTo).exists()) new File(outputTo).mkdir();
TransformerFactory factory = TransformerFactory.newInstance();
Source xsl = new StreamSource(new File(stylesheetPath));
Templates template = factory.newTemplates(xsl);
Transformer transformer = template.newTransformer();
if (!prettyPrint) {
transformer.setOutputProperty(OutputKeys.INDENT, "no");
} else {
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
}
if (excludeDeclaration) transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
Source xml = new StreamSource(new File(filePath + filename));
OutputStream outputStream = new FileOutputStream(outputTo + filename);
transformer.transform(xml, new StreamResult(outputStream));
outputStream.close();
}
使用相同的 XSLT,以下生成的 XML(或来自 XML 的内容)仅包含 Text 节点(无元素、属性等)
public static Document transformInMemory(Document xmlDoc, String stylesheetPath) throws TransformerException, ParserConfigurationException, SAXException, IOException {
TransformerFactory factory = TransformerFactory.newInstance();
Source xsl = new StreamSource(new File(stylesheetPath));
Templates template = factory.newTemplates(xsl);
Transformer transformer = template.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0");
DOMSource source = new DOMSource(xmlDoc);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
transformer.transform(source, new StreamResult(baos));
System.out.println(baos.toString());
// load into DocumentBuilder
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
InputSource is = new InputSource(new ByteArrayInputStream(baos.toByteArray()));
return builder.parse(is);
}
从我一直在做的所有搜索来看,我在第二种方法中似乎没有做错任何事情,但它肯定会产生一些奇怪的结果。
示例结果(不幸的是,我无法发布实际数据,所以我只是将文本替换为其他数据)
<?xml version="1.0" encoding="UTF-8"?>
Some Text Here
A.
Some other text here
B.
Some more text here
C.
And more text here
D.
Even more text here
A
1
我故意将结果格式化,以便您可以准确地看到我所看到的。上面的结果就是System.out.println(baos.toString());
. 如果我在控制台(Eclipse)中突出显示文本,缩进都在那里,但所有元素等都没有显示出来。
所以,我的问题是:谁能告诉我可能发生了什么?为什么第一个工作没有任何问题,但第二个导致上述结果?
编辑:
在玩弄了我的方法之后,我想出了一个似乎可行的解决方法。我没有使用DOMSource
,而是将 xmlDoc 转换为InputStream
,但这似乎有点笨拙。DOMSource
关于为什么会导致这个问题的任何想法?
public static Document transformInMemory(Document xmlDoc, String stylesheetPath) throws TransformerException, ParserConfigurationException, SAXException, IOException {
TransformerFactory factory = TransformerFactory.newInstance();
Source xsl = new StreamSource(new File(stylesheetPath));
Templates template = factory.newTemplates(xsl);
Transformer transformer = template.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0");
// convert the xmlDoc to an inputstream
ByteArrayOutputStream xmlOutStream = new ByteArrayOutputStream();
Source domSource = new DOMSource(xmlDoc);
Result result = new StreamResult(xmlOutStream);
TransformerFactory.newInstance().newTransformer().transform(domSource, result);
InputStream in = new ByteArrayInputStream(xmlOutStream.toByteArray());
//DOMSource source = new DOMSource(xmlDoc);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Source source = new StreamSource(in);
transformer.transform(source, new StreamResult(baos));
System.out.println("baos -> " + baos.toString());
// load into DocumentBuilder
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
InputSource is = new InputSource(new ByteArrayInputStream(baos.toByteArray()));
return builder.parse(is);
}