【问题标题】:Transforming Streaming XSLT Without a Custom Content Handler在没有自定义内容处理程序的情况下转换流式 XSLT
【发布时间】:2014-08-20 11:44:46
【问题描述】:

看看这个网站:

http://xmpp.wordpress.com:8008/firehose.xml?type=text/plain

它不断地传输数据。您可以使用最新版本的 XSLT (v3) 转换此内容,使用如下命令:

<xsl:stream href="http://xmpp.wordpress.com:8008/firehose.xml?type=text/plain">

如果我想编写一些 Java 代码来启动转换(使用已实现 xsl:stream 的 Saxon),我可以这样做:

// XSL
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new FileInputStream(xslFile)));
// XML
StreamSource xmlSource = new StreamSource(new FileInputStream(xmlFile));
// Output
MyCustomContentHandler handler = new MyCustomContentHandler();  
PrintStream outputPrintStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(outputFile)), true);
handler.setPrintStream(outputPrintStream);
Result result = new SAXResult(handler);
// Transform
transformer.transform(xmlSource, result);

这行得通。如果你让它运行一会儿,然后打开输出文件,你会看到其中的数据。如果稍后重新打开它,您会看到更多数据。关键是处理各种 SAX 事件的自定义内容处理程序。

但假设我真的不想要自定义内容处理程序。假设我只想保持 XSLT 的输出不变。我可以像这样修改我的代码:

// XSL
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(new StreamSource(new FileInputStream(xslFile)));
// XML
StreamSource xmlSource = new StreamSource(new FileInputStream(xmlFile));
// Output
TransformerHandler transformerHandler = ((SAXTransformerFactory) SAXTransformerFactory.newInstance()).newTransformerHandler();
transformerHandler.setResult(new StreamResult(new PrintWriter(new FileOutputStream(outputFile, true), true)));
// or this…
//transformerHandler.setResult(new StreamResult(new FileOutputStream(outputFile)));
// or this…
//transformerHandler.setResult(new StreamResult(new FileWriter(outputFile)));
ContentHandler contentHandler = (ContentHandler) transformerHandler;
SAXResult result = new SAXResult(transformerHandler);
// Transform
transformer.transform(xmlSource, result);

好消息是我不再需要自定义内容处理程序,而且我的输出现在与 XSLT 的输出完全匹配。坏消息是,尽管此代码适用于非流式 XSLT,但它不适用于流式 XSLT。尽管我多次尝试设置结果(参见上面的“或这个……”语句),但没有任何内容写入文件。我怀疑存在某种缓冲问题。

问题:如何将这两者中最好的结合在一起?如何在不使用自定义内容处理程序的情况下转换流式 XSLT?

【问题讨论】:

  • 我没有使用过那些东西,但是查看您的代码,第一个版本使用PrintStream 而不是BufferedOutputStream,而在第二个版本中我看不到BufferedOutputStream。您是否尝试在第二个版本中也使用BufferedOutputStream?您的MyCustomContentHandler 看起来可能会有所不同吗?
  • 添加BufferedOutputStream 并没有帮助,因为它仍然需要FileOutputStream 将结果写入文件:transformerHandler.setResult(new StreamResult(new PrintWriter(new BufferedOutputStream(new FileOutputStream(output, true)), true)));
  • 我可以粘贴自定义处理程序的内容,但我看不出这有什么关系。 1)在大多数情况下,它只是试图成为身份功能。 2)我正在努力摆脱它。

标签: java xml xslt streaming saxon


【解决方案1】:

这似乎是 6 月 saxon-help 列表上的一个线程的重新运行:

http://sourceforge.net/p/saxon/mailman/message/32472658/

结论是输出以某种方式被缓冲在输出流管道中。正如您通过提供 ContentHandler 所看到的,Saxon 正在发出表示转换结果的事件,但这些事件的序列化正在 I/O 系统中进行缓冲。

【讨论】:

  • 是的,我应该把链接放回你与罗杰的对话。就我而言,这就是我的原因,但不幸的是,它没有回答我现在的问题:如何在不使用自定义内容处理程序的情况下让 Saxon 支持&lt;xslt:stream&gt;?我无法让它工作。
  • 我不知道发生了什么,但我知道问题不在于撒克逊,而在于下游。 Saxon 不断向输出流发送内容,然后被缓冲。
【解决方案2】:

目前,似乎无法做我想做的事。我当前的解决方案是使用自定义内容处理程序(根据我上面的问题)并通过标准 XSLT 身份转换运行其结果。有点难看,效率不高,但是很管用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多