XSLT Processing with Java : passing xml content in parameter
Asked Answered
D

3

2

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.

Danielldaniella answered 2/2, 2012 at 10:29 Comment(4)
Why dont you strip the tags before passing the parameter??Gerhart
You need to produce a parsed XML document and then pass this as the value of the parameter -- not the string you are now passing. Read your XSLT processor documentation how passing of parameters of type XMLDocument is supported.Sakhuja
@Danielldaniella Maybe you should update your question to reflect how you want to process this parameter - since you dont want to just display it...Gerhart
@quaylar: ok done sorry my first post was confused.Danielldaniella
L
7

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.

Longanimity answered 2/2, 2012 at 13:56 Comment(0)
O
2

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.

Orfinger answered 2/2, 2012 at 11:14 Comment(1)
Ok thanks will have a look at it because I'd like to pass xml so that I'll be able to select nodes in the XSL.Danielldaniella
L
0

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)" />
Lagoon answered 8/2, 2023 at 5:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.