我有这个奇怪的问题,我似乎无法弄明白。到目前为止,我的转换方法似乎几乎完美无缺,但我目前正在构建的工具让我有些头疼。
以下是我的方法:
这个没有错误地工作并产生正确的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,以下内容生成仅包含Text节点的XML(或来自XML的内容)(无元素,属性等)
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
,但这看起来有点像hacky。有关为什么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);
}
答案 0 :(得分:0)
默认情况下,DocumentBuilder不支持名称空间。你需要setNamespaceAware(true)。如果没有名称空间感知,样式表中的模板规则将不匹配,因此默认模板规则会启动,这些只是输出文本节点。
请注意,创建DOM只是为了向XSLT提供输入是一个非常糟糕的主意;使用XSLT处理器的本机树表示几乎肯定会更好。