我尝试使用 XSLT 转换 XML 文档。作为输入,我有 www.wordpress.org XHTML 源代码,而 XSLT 是检索站点标题的虚拟示例(实际上它什么也做不了——它不会改变任何东西)。
我使用的每个 API 或库,转换大约需要 2 分钟!如果您查看 wordpress.org 源代码,您会注意到它只有 183 行代码。当我用谷歌搜索时,这可能是由于 DOM 树构建。无论 XSLT 多么简单,它总是 2 分钟 - 所以它证实了它与 DOM 构建相关的想法,但无论如何我认为它不应该花费 2 分钟。
这是一个示例代码(没什么特别的):
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = null;
try {
transformer = tFactory.newTransformer(
new StreamSource("/home/pd/XSLT/transf.xslt"));
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
System.out.println("START");
try {
transformer.transform(new SAXSource(new InputSource(
new FileInputStream("/home/pd/XSLT/wordpress.xml"))),
new StreamResult(outputStream));
} catch (TransformerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("STOP");
System.out.println(new String(outputStream.toByteArray()));
在 START 和 STOP 之间,java 会“暂停”2 分钟。如果我查看处理器或内存使用情况,没有任何增加。看起来 JVM 真的停止了......
您有转换超过 50(这是随机数 ;))行的 XML 的经验吗?正如我所阅读的那样,XSLT 总是需要构建 DOM 树才能完成它的工作。快速转型对我来说至关重要。
提前致谢, 彼得
最佳答案
示例 HTML 文件是否使用命名空间?如果是这样,您的 XML 解析器可能会尝试从命名空间 URI 中检索内容(可能是模式)。如果每次运行恰好需要两分钟,这很可能发生——很可能是一个或多个 TCP 超时。
您可以通过计算实例化您的 InputSource
对象(实际解析 WordPress XML 的地方)所需的时间来验证这一点,因为这可能是导致延迟的行。查看您发布的示例文件后,它确实包含一个声明的命名空间 (xmlns="http://www.w3.org/1999/xhtml"
)。
要解决此问题,您可以实现自己的 EntityResolver
这实际上禁用了基于 URL 的解析。您可能需要使用 DOM——参见 DocumentBuilder
的 setEntityResolver
方法。
这是一个使用 DOM 并禁用分辨率的示例(注意——这是未经测试的):
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbFactory.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
return null; // Never resolve any IDs
}
});
System.out.println("BUILDING DOM");
Document doc = db.parse(new FileInputStream("/home/pd/XSLT/wordpress.xml"));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(
new StreamSource("/home/pd/XSLT/transf.xslt"));
System.out.println("RUNNING TRANSFORM");
transformer.transform(
new DOMSource(doc.getDocumentElement()),
new StreamResult(outputStream));
System.out.println("TRANSFORMED CONTENTS BELOW");
System.out.println(outputStream.toString());
} catch (Exception e) {
e.printStackTrace();
}
关于java - Java 中极慢的 XSLT 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4799136/