Reputation: 1360
I would like to pass a parameter containing XML content when processing XSLT. Here is my code:
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
File xmlFile = new File(xmlFilePath);
File xsltFile = new File(xslFilePath);
Source xmlSource = new StreamSource(xmlFile);
Result result = new StreamResult(System.out);
TransformerFactory transFact = TransformerFactory.newInstance();
Transformer trans = transFact.newTransformer(xsltSource);
trans.setParameter("foo", "<bar>Hello1</bar><bar>Hello2</bar>");
trans.transform(xmlSource, result);
Then I'd like to select the values contained in the 'bar' tag in my XSL file.
<xsl:param name="foo"/>
...
<xsl:value-of select="$foo//foo[1]" />
But this doesn't work, I get this error message:
org.apache.xpath.objects.XString cannot be cast to org.apache.xpath.objects.XNodeSet
So I guess I should pass an XML object to my setParameter method, but which one? I can't find a simple example how to create an XNodeSet object...
How can I do that? Thanks.
Upvotes: 2
Views: 7157
Reputation: 19565
If you are using Xalan (the built-in implementation in the Java JDK), then pass a "URI" as the parameter value, which is any value you wish that is mapped in the subsequent step:
setParameter("foo", "myxml")
Now, define a URIResolver
on the transformer (example in Kotlin, but the java translation is straightforward):
val transformer = factory.newTransformer(...)
transformer.setURIResolver { href, base ->
when (href) {
"myxml" -> StreamSource(StringReader("<bar>baz</bar>"))
else -> error("Cannot resolve href $href")
}
}
Define as many URIs and mappings to Source
's as necessary.
In the stylesheet, use the document
function to pass the URI String parameter to the custom URIResolver
and transform it into an XML document:
<xsl:param name="foo" />
<xsl:param name="fooDoc" select="document($foo)" />
Upvotes: 0
Reputation: 167401
You might want to check the documentation of your XSLT processor what kind of parameter types it allows and whether and how it allows to pass in a node and not a string. If I understand http://www.saxonica.com/html/documentation/using-xsl/embedding/jaxp-transformation.html and http://www.saxonica.com/html/documentation/javadoc/net/sf/saxon/jaxp/TransformerImpl.html#setParameter(java.lang.String,%20java.lang.Object) correctly then Saxon allows you to pass in nodes in the form of its NodeInfo
.
Upvotes: 2
Reputation: 163262
If you are using Saxon, the simplest solution is to pass a StreamSource as the parameter value:
setParameter("foo", new StreamSource(new StringReader("<bar>baz</bar>")));
But this might not work with other processors: JAXP leaves it implementation-defined what kinds of Object can be passed as parameter values.
Upvotes: 7