将 xml 节点/文档/片段作为参数传递给 xslt

发布于 2024-09-25 06:34:44 字数 901 浏览 0 评论 0原文

我尝试将 w3c.dom.DocumentElementNodeList 作为参数传递给 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’到‘节点集’的转换无效。”

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

看起来 xalan 在内部除了他自己的 Node.js 实现之外。

我怎样才能做类似的事情而不遇到这个问题?

我无法使用 document($param) 因为我是动态构建文档的。

I tried to pass a w3c.dom.Document, Element and NodeList as parameters to a xslt transform.

I want to be able to process it within the xslt:

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

I pass the parameter as:

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

I get this exception:

'Invalid conversion from 'com.sun.org.apache.xerces.internal.dom.DocumentImpl' to 'node-set'.'

I tried also exslt:node-set(), xalan:nodeset() etc, but it doesn't work.

It seems that internally xalan excepts his own implementation of the Node.

How can I do something similar without incurring in this problem?

I cannot use document($param) because I construct the doc on the fly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谁人与我共长歌 2024-10-02 06:34:44

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

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

那么,有哪些替代方案呢?

  1. 乱搞 URI,如中所述
    如何传递节点的响应
    作为 XSLTC 转换的参数
    处理器
  2. 后代替
    XALAN 编译处理器(XSLTC),
    使用 XALAN 解释处理器。或任何其他支持此类行为的 XSLT 处理器。
  3. 使用 DTMAxisIterator
    相反,也在对 如何通过节点
    作为 XSLTC 转换的参数
    处理器后 - 但不确定它是否会工作。
  4. 创建一个新的 DOM 树,将“参数”DOM 和原始 XSLT 输入文档结合起来

(Posting a new answer, as the previous one did not solve the issue and this new one is radically different from the previous)

Seems to be a known issue with XALAN compiling processor ( XALANJ-2057,
How can I pass a node as parameter to translets for XSLTC Processor).

So, what are the alternatives?

  1. mess around with URIs as outlined in
    a response to How can I pass a node
    as parameter to translets for XSLTC
    Processor
    post
  2. Instead of
    XALAN compiling processor (XSLTC),
    use XALAN interpretive processor. Or any other XSLT processor that supports such behavior.
  3. Use DTMAxisIterator
    instead, also outlined in a response to How can I pass a node
    as parameter to translets for XSLTC
    Processor
    post - not sure if it will work, though.
  4. Create a new DOM tree, combining your "parameter" DOM and the original XSLT input document
ˉ厌 2024-10-02 06:34:44

我找到了一个解决方案(此处:使用Java进行XSLT处理:传递xml参数中的内容),这也可能适合您的情况:

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 进行测试,但也许答案会帮助其他偶然发现这个问题的人:)

I found a solution (here: XSLT Processing with Java : passing xml content in parameter) which may work for your case as well:

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

instead of creating a uriresolver from a string, just create a stream source from a string reader and pass it to the stylesheet.

After that, I was able to access the doc normally as XML:

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

Did not test with xalan, but maybe the answer will help others who stumble onto this question :)

仲春光 2024-10-02 06:34:44

这是 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>...

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

Here's a working example with the URIResolver Gambit, #1 in the list of solutions:

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.
        }

    }
}

I also had a working version where I put the xml source in the URI like

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

but I figured that might run into length limits somewhere.

缱倦旧时光 2024-10-02 06:34:44

如果您查看文档JavaDoc,可以看到它扩展了 Node 接口,但不是 节点列表。不确定它是否有效,但您可以尝试传入 params.getChildNodes() 而不是 params

If you look at the Document JavaDoc, you can see that it extends Node interface, but not NodeList. Not sure if it will work, but you could try to pass in params.getChildNodes() instead of params.

缪败 2024-10-02 06:34:44

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

It's an annoyance, one way or the other. In the end, I've always found it easiest and most compatible with other XSLT processors to serialize the XML fragment to a temp file, pass that file's URI to XSLT as a string parameter, and from there load the URI via the XPath document() function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文