Re: [xsl] Subject: RE: [xsl] XML fragment as a param ?

Subject: Re: [xsl] Subject: RE: [xsl] XML fragment as a param ?
From: "Nick Fitzsimons" <nick@xxxxxxxxxxxxxx>
Date: Tue, 15 Nov 2005 18:37:57 -0000 (GMT)
> When I do this :-
>
> transformer.setParameter(param.name, param.value);
>
> where param.name and param.value are both Strings and contain -
> "inboundXML"
> and "<Numbers><Odds><One>1</One>... "
>
> and when the stylesheet looks like this :-
>
> ...
>   <xsl:param name="inboundXML" select="/"/>
>   <xsl:template match="/">
>     <rootContainer>
>         <xsl:copy-of select="$inboundXML"/>
>     </rootContainer>
>   </xsl:template>
> ...
>
> I get this (almost correct but no cigar :-) :-
>
> <rootContainer>
>         &lt;Numbers&gt;&lt:Odds&gt;&lt;One&gt;1.....
> </rootContainer>
>

That's because you passed in a string containing characters which have to
be escaped in XML ("<" and ">" for example), so they were escaped to
ensure that the output was well-formed. You could use
"disable-output-escaping" if passing in a string is the path you want to
pursue.

>
> Previously Michael commented :-
>

> Michael> Most products will allow you to supply a DOM
> node (they
> Michael> may restrict which DOM implementations you are allowed to use).
> Saxon allows
> Michael> you to supply any JAXP Source object, so if you supply a
> StreamSource
> Michael> containing raw XML, the XML will be parsed and the stylesheet
> will
> see the
> Michael> resulting document node as the parameter value.
>
> That's interesting I thought so I tried doing this (admittedly I'm not
> using
> Saxon (sorry Michael) so no guarantees) :-
>
> transformer.setParameter(param.name, new StreamSource(new
> StringReader(param.value)));
>
> but unfortunately all that gave me was :-
>
> <rootContainer>javax.xml.transform.stream.StreamSource@4c6ca8b6</rootContainer>
>

Which is also correct (in your environment) as that is the string
representation of the StreamSource: clearly the processor you are using
doesn't support using a StreamSource as a parameter, and so took the
result of that object's toString() method.

Have you tried passing a DOM node, as Michael suggested before mentioning
the StreamSource? You could then use:

   <xsl:param name="inboundXML" select="/"/>
   <xsl:template match="/">
     <rootContainer>
         <xsl:apply-templates select="$inboundXML"/>
     </rootContainer>
   </xsl:template>

   <xsl:template match="Numbers">
      <!-- at this point you have matched the Numbers element in
           your inboundXML DOM, so do whatever you planned with it
      -->
   </xsl:template>

If the XML you want to pass in is already in DOM form, then just use
setParameter (the following is JavaScript/MSXML, but should give you the
idea):

var requiredNode =
additionalDocument.selectSingleNode("/document/containing/desired/Numbers");
xslProcessor.addParameter("inboundXML", requiredNode); // setParameter in
your case
xslProcessor.transform();

If you have the XML as a string, you'll probably want to scroll back up
and look into the disable-output-escaping option, although this can have
undesired side effects: in the future, somebody could pass any string into
your code and make it produce ill-formed output (for example, passing in
"<<<").

> I have tried using the exslt:node-set function, but I'm not sure I got it
> correct.
>

The extension "node-set" function will convert a result tree fragment into
a node set, so isn't really relevant in this case - although I may be
wrong, as every time I mention result tree fragments I make some basic
mistake, which Michael kindly corrects :-)

HTH,

Nick.
-- 
Nick Fitzsimons
http://www.nickfitz.co.uk/

Current Thread