7

我试图将w3c.dom.Document,ElementNodeList作为参数传递给 xslt 转换。

我希望能够在 xslt 中处理它:

<xsl:param name="links" />
<xsl:template match="/">
    <record>
        <xsl:for-each select="$links/*">
            <test />
        </xsl:for-each>
    </record>
</xsl:template>

我将参数传递为:

        Document params = createLinksParams(links);
        transformer.setParameter("links", params);

我得到这个例外:

'从'com.sun.org.apache.xerces.internal.dom.DocumentImpl'到'node-set'的无效转换。'

我也试过exslt:node-set()xalan:nodeset()等等,但它不起作用。

似乎 xalan 在内部排除了他自己的 Node.js 实现。

我怎样才能做类似的事情而不会出现这个问题?

我不能使用document($param),因为我是动态构建文档的。

4

5 回答 5

4

(发布一个新的答案,因为前一个没有解决问题,而这个新的答案与以前的完全不同)

似乎是 XALAN 编译处理器的一个已知问题(XALANJ-2057如何将节点作为参数传递给 XSLTC 处理器的 translets)。

那么,有哪些替代方案?

  1. 如对如何将节点作为参数传递给 XSLTC 处理器帖子的 translets的响应中所述,弄乱了 URI
  2. 使用 XALAN 解释处理器代替 XALAN 编译处理器 (XSLTC) 。或任何其他支持此类行为的 XSLT 处理器。
  3. 使用 DTMAxisIterator 代替,也在对如何将节点作为参数传递给 XSLTC 处理器后的 translets 的响应中进行了概述 - 但不确定它是否会工作。
  4. 创建一个新的 DOM 树,结合您的“参数”DOM 和原始 XSLT 输入文档
于 2010-09-25T10:48:27.067 回答
4

我找到了一个解决方案(此处:XSLT Processing with Java : passing xml content in parameter),它也可能适用于您的情况:

String urls = "<urls><url id='google'>https://www.google.com</url>...";
trans.setParameter("lookupdoc", new StreamSource(new StringReader(urls)));

无需从字符串创建 uriresolver,只需从字符串阅读器创建流源并将其传递给样式表。

之后,我能够以 XML 的形式正常访问文档:

<xsl:param name="lookupdoc"><urls/></xsl:param> 
... 
<xsl:variable name="googleurl" select="$lookupdoc/@id='google"/>

没有用 xalan 测试,但也许答案会帮助其他偶然发现这个问题的人:)

于 2012-12-27T16:31:00.670 回答
1

这是一个使用 URIResolver Gambit 的工作示例,解决方案列表中的 #1:

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.StringReader;
import java.io.StringWriter;

public class XSLTest {
    public static void main(String[] args) {

        class MyResolver implements URIResolver {
            String _xml;
            MyResolver(String xml) { _xml = xml; }
            @Override
            public Source resolve(String href, String base) throws TransformerException {
                return new StreamSource(new StringReader(_xml));
            }
        }

        String lookup =
            "<?xml version='1.0' encoding='utf-8'?>\n" +
            "<urls>\n" +
            "    <url id='google'>https://www.google.com</url>\n" +
            "    <url id='yahoo'>https://www.yahoo.com</url>\n" +
            "    <url id='apple'>https://www.apple.com</url>\n" +
            "</urls>";

        String main =
            "<?xml version='1.0' encoding='utf-8'?>" +
            "<list>"+
            "   <link ref='yahoo'>Yahoo</link>"+
            "   <link ref='google'>Google</link>"+
            "</list>";

        String xsl =
            "<?xml version='1.0' encoding='UTF-8'?>\n" +
            "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" +
            "    <xsl:param name='lookup-doc' />\n" +
            "    <xsl:variable name='lookup' select='document($lookup-doc)'/>\n" +
            "    <xsl:template match='/'>\n" +
            "        <xsl:for-each select='//link'>\n" +
            "            <xsl:variable name='ref' select='@ref'/>\n" +
            "            <xsl:element name='a'>\n" +
            "                <xsl:attribute name='href'>\n" +
            "                    <xsl:value-of select='$lookup//url[@id=$ref]'/>\n" +
            "                </xsl:attribute>\n" +
            "                <xsl:value-of select='text()'/>\n" +
            "            </xsl:element>\n" +
            "        </xsl:for-each>\n" +
            "    </xsl:template>\n" +
            "</xsl:stylesheet>";

        try {

            // xsl doc
            Source xsltSource = new StreamSource(new StringReader(xsl));

            TransformerFactory transFact = TransformerFactory.newInstance();
            Transformer trans = transFact.newTransformer(xsltSource);

            // main doc
            Source mainSource = new StreamSource(new StringReader(main));

            // lookup doc - stage it in the URI resolver
            trans.setURIResolver(new MyResolver(lookup));
            // dummy URL, you could use different values here to 
            // support multiple document parameters
            trans.setParameter("lookup-doc", "xml://lookup");

            StringWriter out = new StringWriter();
            trans.transform(mainSource, new StreamResult(out));

            System.out.println(out.toString());

        } catch (TransformerException e) {
            System.err.println("It's the wrong trousers Gromit, and they've gone wrong!");
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

    }
}

我还有一个工作版本,我将 xml 源代码放在URI 中,例如

xml://<urls><url><url id='google'>https://www.google.com</url>...

但我认为这可能会在某处遇到长度限制。

于 2012-11-08T01:55:42.003 回答
0

如果您查看Document JavaDoc,您可以看到它扩展了Node接口,但没有扩展NodeList。不确定它是否会起作用,但您可以尝试传入params.getChildNodes()而不是params

于 2010-09-24T17:32:34.293 回答
0

这是一种烦恼,一种或另一种方式。最后,我总是发现最简单且与其他 XSLT 处理器最兼容的方法是将 XML 片段序列化为临时文件,将该文件的 URI 作为字符串参数传递给 XSLT,然后从那里通过 XPath 文档加载 URI( ) 功能。

于 2019-08-13T15:40:41.943 回答