【问题标题】:Accessing unparsed entities in XSLT with a SAXTransformerFactory and TransformerHandlers使用 SAXTransformerFactory 和 TransformerHandlers 访问 XSLT 中未解析的实体
【发布时间】:2017-04-13 08:23:44
【问题描述】:

我在使用 XPath 函数 unparsed-entity-uri() 检索未解析的实体 URI 时遇到了一些麻烦。

我使用SAXTransformerFactory 就像在"Efficient XSLT pipeline in Java" question 中一样,因为我需要执行一个转换链(即应用多个 XSLT 转换,并将转换的结果用作第二个转换的输入)。

感谢下面的代码,我发现我无法检索未解析的实体。 实际上它适用于 Xalan,但不适用于 Saxon-HE(版本 9.7.0) - 但我需要 Saxon,因为我更喜欢 XSLT 2.0(即使在下面的代码中没有任何特定于 XSLT 的内容2,只是为了举例)。如果我不使用 TransformerHandler,它也适用于 Saxon,例如stf.newTransformer(new StreamSource("transfo.xsl")).transform(new StreamSource("input.xsl"), new StreamResult(System.out)) 将产生所需的输出。

是否有我忘记的配置步骤?

    // use "org.apache.xalan.processor.TransformerFactoryImpl" for Xalan
    String transformerFactoryClassName = "net.sf.saxon.TransformerFactoryImpl";
    SAXTransformerFactory stf = (SAXTransformerFactory) TransformerFactory.newInstance(transformerFactoryClassName,
            LaunchSimpleTransformationUnparsedEntities.class.getClassLoader());
    try {
        TransformerHandler thTransf = stf
                .newTransformerHandler(new StreamSource("transfo.xsl"));

        // output the result in console
        thTransf.setResult(new StreamResult(System.out));

        // Launch transformation of input.xml
        Transformer t = stf.newTransformer();
        t.transform(new StreamSource("input.xml"),
                new SAXResult(thTransf));

    } catch (TransformerConfigurationException e) {
        e.printStackTrace();
    } catch (TransformerException e) {
        e.printStackTrace();
    }

在输入中,我有(对于 input.xml):

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE book
[<!ENTITY cover_hadrien SYSTEM "images/covers/cover_hadrien.jpg" NDATA jpeg>]>
<book>
  <title>Les mémoires d'Hadrien</title>
  <author>Marguerite Yourcenar</author>
  <cover imgref="cover_hadrien" />
</book>

和一个示例 XSLT(用于 transfo.xsl):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="cover">
      <xsl:copy>
        <xsl:value-of select="unparsed-entity-uri(@imgref)"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

因此,我希望得到类似的结果:

<?xml version="1.0" encoding="UTF-8"?><book>
  <title>Les mémoires d'Hadrien</title>
  <author>Marguerite Yourcenar</author>
  <cover>images/covers/cover_hadrien.jpg</cover>
</book>

&lt;cover&gt; 在使用 Saxon 执行转换时为空。

【问题讨论】:

    标签: java xslt saxon


    【解决方案1】:

    有趣的观察。事实上,问题不在于 Saxon 的 TransformerHandler,而在于使用 SAXTransformerFactory.newTransformer() 获得的“身份转换器”:身份转换器没有将未解析的实体传递到线上。这本质上是因为 Saxon 的身份转换器正在重用 XSLT 引擎的部分内容,而 XSLT 没有提供任何方式来进行转换以在结果中输出未解析的实体。如果您将 SAX 解析器输出直接发送到 TransformerHandler,而不是通过身份转换器,那么我认为这一切都会奏效。

    与所有与 JAXP 相关的东西一样,SAXTransformerFactory.newTransformer() 的规范非常模糊。它只是说返回的 Transformer 将 Source 复制到 Result。即“身份转换”。究竟什么算作副本?我认为 Saxon 的解释是,它等同于进行 XSLT 身份转换的效果 - 这会丢失未解析的实体(以及 CDATA 部分、DTD 等其他内容)。

    顺便说一句,XSLT 2.0 指定 unparsed-entity-uri() 的结果应该是一个绝对 URI(XSLT 1.0 没有说明任何关于该主题的内容)所以即使这个问题已修复,Saxon 输出也会有所不同。

    在此处作为撒克逊问题输入:https://saxonica.plan.io/issues/3201 我认为如果我们不传递 SAX DTDHandler 预期的所有其他事件,我们需要小心将未解析的实体传递给 SAXResult - 我们当然是不会更改撒克逊身份转换器以保留未在 XDM 中建模的内容(如 DTD 声明)。

    【讨论】:

    【解决方案2】:

    确实,按照@MichaelKay 的详细信息,以这种方式启动转换工作正常:

            // launch transformation of input.xml
            XMLReader reader = XMLReaderFactory.createXMLReader();
            reader.setContentHandler(thTransf);
            reader.setDTDHandler(thTransf);
            reader.parse(new InputSource(input.xml"));
    

    (这将替换以下行:

            // Launch transformation of input.xml
            Transformer t = stf.newTransformer();
            t.transform(new StreamSource("input.xml"),
                    new SAXResult(thTransf));
    

    最初使用的)。

    【讨论】:

    • thTransf 也指定为LexicalHandler 可能是个好主意,否则您将失去cmets。
    猜你喜欢
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-01
    • 2012-09-03
    相关资源
    最近更新 更多