我尝试将w3c.dom.Document
,Element
和NodeList
作为参数传递给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实现。
如何在不引发此问题的情况下执行类似操作?
我无法使用document($param)
,因为我会动态构建文档。
答案 0 :(得分:4)
(发布一个新的答案,因为前一个答案没有解决问题,这个新问题与之前完全不同)
似乎是XALAN编译处理器(XALANJ-2057)的已知问题, How can I pass a node as parameter to translets for XSLTC Processor)。
那么,有哪些替代方案?
答案 1 :(得分: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,只需从字符串阅读器创建一个流源并将其传递给样式表。
之后,我能够正常访问doc作为XML:
<xsl:param name="lookupdoc"><urls/></xsl:param>
...
<xsl:variable name="googleurl" select="$lookupdoc/@id='google"/>
没有用xalan测试,但也许答案会帮助那些偶然发现这个问题的人:)
答案 2 :(得分:1)
以下是URIResolver Gambit的一个工作示例,解决方案列表中排名第一:
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>...
但我认为可能会在某处遇到长度限制。
答案 3 :(得分:0)
如果您查看Document JavaDoc,可以看到它扩展了Node界面,而不是NodeList。不确定它是否可行,但您可以尝试传入 params.getChildNodes()而不是 params 。
答案 4 :(得分:0)
这是一种烦人,一种或另一种方式。最后,我总是发现它与其他XSLT处理器最简单,最兼容,可以将XML片段序列化为临时文件,将该文件的URI作为字符串参数传递给XSLT,然后从那里通过XPath文档加载URI( )功能。