You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cocoon.apache.org by Viktors Rotanovs <vi...@riga.nu> on 2000/09/22 01:13:03 UTC

passing data to xsp:logic

Hi,

did you ever have this problem? In xml, I write something like this:
<my:tag>i want to go back and <request:get-parameter name="forward"/></my:tag>
And then try to pass what's inside the tag to xsp:logic in the logicsheet in 
many ways, just some of them:
myMethod(<xsl:value-of select="."/>)
or 
myMethod("<xsl:value-of select="."/>")
or by setting variable to what xsl:apply-templates evaluates.

And, I don't know when to put value into quotes, when do not put, and 
sometimes method called by <request:get-parameter/> silently disappears.
What will happen if data cames from form and user puts &quot; into input
field? Will it evaluate as Java code?

I have even tried get-nested-string and get-nested-content templates
from esql logicsheet, and it didn't help (but everything works ok if I don't
mix tags with strings inside <my:tag></my:tag). What to do?

-- 
Best Wishes,
Viktors Rotanovs
I create websites that attract more clients. http://riga.nu/
Riga Latvia +371, Phone 7377-142, GSM 9173-000, FAX 7377-472

Re: get-nested-content & get-parameter question

Posted by Jeremy Quinn <je...@media.demon.co.uk>.
At 03:08 +0200 22/09/00, Viktors Rotanovs wrote:
>I had the same problem - see previous messages.
>No answer yet.
>Probably this is the Frequently-Asked-Never-Answered-Question :-)
>There should be some explanation on how Cocoon converts
>tags and strings to method calls.
>
>On Fri, 22 Sep 2000, you wrote:
>> Hi,
>>
>> I see the template 'get-nested-content' used all over the place in
>> the built-in tag libs... Can someone explain its motivation and use?
>> Why is it needed?

As I understand it, the 'get-nested-content' template allows the use of
other TagLibs inside yours.

ie.

	<fp:write to="external-file" select="blah">
		<request:get-parameter name="field_named_blah"/>
	</fp:write>

hope this helps

regards Jeremy
-- 
   ___________________________________________________________________

   Jeremy Quinn                                           Karma Divers
                                                       webSpace Design
                                            HyperMedia Research Centre

   <ma...@mac.com>     		 <http://www.media.demon.co.uk>
    <phone:+44.[0].20.7737.6831>        <pa...@sms.genie.co.uk>

Re: get-nested-content & get-parameter question

Posted by Viktors Rotanovs <vi...@riga.nu>.
Hi,

I had the same problem - see previous messages.
No answer yet.
Probably this is the Frequently-Asked-Never-Answered-Question :-)
There should be some explanation on how Cocoon converts
tags and strings to method calls.

On Fri, 22 Sep 2000, you wrote:
> Hi,
>
> I see the template 'get-nested-content' used all over the place in
> the built-in tag libs... Can someone explain its motivation and use?
> Why is it needed?
>
> I have an XML page and two tag libs (see below). The first tag lib
> works fine. The second one gives me a compile error (in the String
> assignment because the get-parameter name="def" simply substitutes an
> empty string). I'm not using 'get-nested-content'. Should I be?
> Anyone have any ideas why the substitution for get-parameter
> name="def" wouldn't substitute in the same one the other one ("abc")
> substitutes?
>
> Sorry for the complex question -- hopefully someone has seen and
> solved a similar problem...
>
> Chris
>
> ------------------------------------
> <?xml version="1.0"?>
> <?xml-stylesheet href="index.xsl" type="text/xsl"?>
> <?cocoon-process type="xsp"?>
> <?cocoon-process type="xslt"?>
>
> <xsp:page
>    language="java"
>    create-session="true"
>    xmlns:sql="http://www.apache.org/1999/SQL"
>    xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>    xmlns:request="http://www.apache.org/1999/XSP/Request"
>    xmlns:mytaglib1="http://mystuff.com/mytaglib1"
>    xmlns:mytaglib2="http://mystuff.com/mytaglib2"
>
>
> <content>
>    <mytaglib1:dosomething>
>      <parameter><request:get-parameter name="abc"></parameter>
>    </mytaglib1:dosomething>
>
>    <mytaglib2:dosomethingelse>
>      <parameter2><request:get-parameter name="def"></parameter2>
>    </mytaglib2:dosomethingelse>
> </content>
> ------------------------------------
>
> I also have tag libs that look like this:
>
> ------------------------------------
> <?xml version="1.0"?>
>
> <xsl:stylesheet version="1.0"
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>    xmlns:mytaglib1="http://mystuff.com/mytaglib1"
>
>
> <xsl:template match="xsp:page">
>    <xsp:page>
>      <xsl:apply-templates select="@*"/>
>      <xsl:apply-templates/>
>    </xsp:page>
> </xsl:template>
>
> <xsl:template match="mytaglib1:dosomething">
>    <xsp:logic>
>    {
>    String xx = <xsl:value-of select="parameter"/>;
>    }
>    </xsp:logic>
> </xsl:template>
>
> <xsl:template match="@*|*|text()|processing-instruction()">
>    <xsl:copy>
>      <xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
>    </xsl:copy>
> </xsl:template>
>
> </xsl:stylesheet>
> ------------------------------------
>
> and
>
> ------------------------------------
> <?xml version="1.0"?>
>
> <xsl:stylesheet version="1.0"
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>    xmlns:mytaglib2="http://mystuff.com/mytaglib2"
>
>
> <xsl:template match="xsp:page">
>    <xsp:page>
>      <xsl:apply-templates select="@*"/>
>      <xsl:apply-templates/>
>    </xsp:page>
> </xsl:template>
>
> <xsl:template match="mytaglib2:dosomethingelse">
>    <xsp:logic>
>    {
>    String yy = <xsl:value-of select="parameter2"/>;
>    }
>    </xsp:logic>
> </xsl:template>
>
> <xsl:template match="@*|*|text()|processing-instruction()">
>    <xsl:copy>
>      <xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
>    </xsl:copy>
> </xsl:template>
>
> </xsl:stylesheet>
> ------------------------------------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: cocoon-users-unsubscribe@xml.apache.org
> For additional commands, e-mail: cocoon-users-help@xml.apache.org

-- 
Best Wishes,
Viktors Rotanovs
I create websites that attract more clients. http://riga.nu/
Riga Latvia +371, Phone 7377-142, GSM 9173-000, FAX 7377-472

Re: get-nested-content & get-parameter question

Posted by Donald Ball <ba...@webslingerZ.com>.
On Thu, 21 Sep 2000, Chris Meyer wrote:

> Thanks for the great response! It is very instructive and hopefully 
> will make it into a FAQ sometime. I suspected something along the 
> lines of what you explained, but your explanation helps clear things 
> up for me. What threw me off was that one of my tag libs got applied 
> and so one case worked correctly and one didn't...

i'm glad it was helpful. i hope one or another of the would-be documenters
will take the trouble to turn it into something real? i know i'm never
going to write something that long on the subject again. :)

> As I understand it there are three main points in your response:
> 
> 1. If you depend on request time conditions you must make sure that 
> they're evaluated in the proper context. One way to do this is to use 
> the get-nested-content or get-nested-string templates.
> 
> 2. One should not use xsp:logic sub-blocks in expressions that will 
> typically (ever) be used as strings because that prohibits them from 
> being used as such.
> 
> 3. Taglib writers should take care to only expose desired variables 
> outside of a scope defined in the tag lib and should probably prefix 
> their internal variables to avoid conflicts with other less taglib 
> writers.

that's pretty much the gist of it, yes.

> Just some additional remarks/ideas that I haven't fully thought 
> through but might spur some ideas for other people:
> 
> - Could there be an extension to xsp like xsp:string and xsp:content 
> which implemented those items automatically? That way they wouldn't 
> have to be duplicated all over the place?

there is an xsp:content element already, it's used when you want to
evaluate an xsp:expr element directly underneath xsp:logic element. i'm
not even really sure how you'd use the elements you suggest though - can
you perhaps give an example?

> - Could we use java introspection to simplify the case of generating 
> 'end-of-the-tree' XML from java objects?

you can have your java objects implement the XObject interface if you want
them to be serializable as xml. i suppose you could write a factory method
to use reflection to do something similar for non-XObjects. if you're
really interested in that, you might want to check out castor
(http://castor.exolab.org/). they've got a sophisticated object<->xml
mapping layer.

> - One additional problem (different topic) I'm trying to think of a 
> solution for is that of one taglib depending on variables defined in 
> another tag lib. For instance, I may have a general tag lib which 
> handles a user logging into the system, checking of the password, 
> saving out the object to the session, etc. But if I want to have 
> another taglib that implements an application (say a shopping cart) 
> then I have to use variables from the first tag lib --OR-- define 
> much more cumbersome 'accessors' for inserting that variable into the 
> applications... Does this problem make sense? Or has someone else 
> solved it a different way? Or am I just missing some simple point?

sure, your problem makes sense. for this particular application, i think
you would be well served by using session variables for inter-logicsheet
communication. can you think of another example where neither of the two
paradigms we've discussed so far (result expressions, session
variables) would work well?

- donald


Re: get-nested-content & get-parameter question

Posted by Chris Meyer <cm...@ultratask.com>.
Hi Donald,

Thanks for the great response! It is very instructive and hopefully 
will make it into a FAQ sometime. I suspected something along the 
lines of what you explained, but your explanation helps clear things 
up for me. What threw me off was that one of my tag libs got applied 
and so one case worked correctly and one didn't...

As I understand it there are three main points in your response:

1. If you depend on request time conditions you must make sure that 
they're evaluated in the proper context. One way to do this is to use 
the get-nested-content or get-nested-string templates.

2. One should not use xsp:logic sub-blocks in expressions that will 
typically (ever) be used as strings because that prohibits them from 
being used as such.

3. Taglib writers should take care to only expose desired variables 
outside of a scope defined in the tag lib and should probably prefix 
their internal variables to avoid conflicts with other less taglib 
writers.

Just some additional remarks/ideas that I haven't fully thought 
through but might spur some ideas for other people:

- Could there be an extension to xsp like xsp:string and xsp:content 
which implemented those items automatically? That way they wouldn't 
have to be duplicated all over the place?

- Could we use java introspection to simplify the case of generating 
'end-of-the-tree' XML from java objects?

- One additional problem (different topic) I'm trying to think of a 
solution for is that of one taglib depending on variables defined in 
another tag lib. For instance, I may have a general tag lib which 
handles a user logging into the system, checking of the password, 
saving out the object to the session, etc. But if I want to have 
another taglib that implements an application (say a shopping cart) 
then I have to use variables from the first tag lib --OR-- define 
much more cumbersome 'accessors' for inserting that variable into the 
applications... Does this problem make sense? Or has someone else 
solved it a different way? Or am I just missing some simple point?

Chris

Re: get-nested-content & get-parameter question

Posted by Donald Ball <ba...@webslingerZ.com>.
On Thu, 21 Sep 2000, Chris Meyer wrote:

> I see the template 'get-nested-content' used all over the place in 
> the built-in tag libs... Can someone explain its motivation and use? 
> Why is it needed?

it's needed to properly access the value of nested content (neat,
huh?) (yes, i'll explain!)

> I have an XML page and two tag libs (see below). The first tag lib 
> works fine. The second one gives me a compile error (in the String 
> assignment because the get-parameter name="def" simply substitutes an 
> empty string). I'm not using 'get-nested-content'. Should I be? 
> Anyone have any ideas why the substitution for get-parameter 
> name="def" wouldn't substitute in the same one the other one ("abc") 
> substitutes?

as i read it, neither of your logicsheets will work as intended. let's
step through it piece by piece.

> <?xml version="1.0"?>
> <?xml-stylesheet href="index.xsl" type="text/xsl"?>
> <?cocoon-process type="xsp"?>
> <?cocoon-process type="xslt"?>
> 
> <xsp:page
>    language="java"
>    create-session="true"
>    xmlns:sql="http://www.apache.org/1999/SQL"
>    xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>    xmlns:request="http://www.apache.org/1999/XSP/Request"
>    xmlns:mytaglib1="http://mystuff.com/mytaglib1"
>    xmlns:mytaglib2="http://mystuff.com/mytaglib2"
> >
> 
> <content>
>    <mytaglib1:dosomething>
>      <parameter><request:get-parameter name="abc"></parameter>
>    </mytaglib1:dosomething>
> 
>    <mytaglib2:dosomethingelse>
>      <parameter2><request:get-parameter name="def"></parameter2>
>    </mytaglib2:dosomethingelse>
> </content>

i assume that your request:get-parameter elements are really singletons in
your reql source and that you close the xsp:page element. :) now you know
how xsp works, right? a series of xslt stylesheets are applied to your
source document, resulting in a java source file which is compiled into
bytecode and executed repeatedly. it really shouldn't matter in which
order the stylesheets (called logicsheets or taglibs) are applied, but for
sake of argument, let's say your logicsheets are invoked first. after the
first is applied, you end up with this (more or less):

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="index.xsl" type="text/xsl"?>
<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-logicsheet href="mytaglib1.xsl"?>
<?xml-logicsheet href="mytaglib2.xsl"?>
<xsp:page
 xmlns:mytaglib1="http://mystuff.com/mytaglib1" 
 xmlns:xsp="http://www.apache.org/1999/XSP/Core" 
 language="java" 
 create-session="true"
>

<content 
 xmlns:sql="http://www.apache.org/1999/SQL"
 xmlns:request="http://www.apache.org/1999/XSP/Request" 
 xmlns:mytaglib2="http://mystuff.com/mytaglib2"
>
   <xsp:logic>
   {
   String xx = ;
   }
   </xsp:logic>

   <mytaglib2:dosomethingelse>
     <parameter2><request:get-parameter name="def"/></parameter2>
   </mytaglib2:dosomethingelse>
</content>

</xsp:page>

that's not what you want, but looking at your stylesheet:

> <?xml version="1.0"?>
> 
> <xsl:stylesheet version="1.0"
>    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>    xmlns:xsp="http://www.apache.org/1999/XSP/Core"
>    xmlns:mytaglib1="http://mystuff.com/mytaglib1"
> >
> 
> <xsl:template match="xsp:page">
>    <xsp:page>
>      <xsl:apply-templates select="@*"/>
>      <xsl:apply-templates/>
>    </xsp:page>
> </xsl:template>
> 
> <xsl:template match="mytaglib1:dosomething">
>    <xsp:logic>
>    {
>    String xx = <xsl:value-of select="parameter"/>;
>    }
>    </xsp:logic>
> </xsl:template>
> 
> <xsl:template match="@*|*|text()|processing-instruction()">
>    <xsl:copy>
>      <xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
>    </xsl:copy>
> </xsl:template>
> 
> </xsl:stylesheet>

that's the result of taking calling value-of on the parameter
element. value-of concatenates all of the text descendents of an
element. what you're looking for is the ultimate value of whatever is
beneath the current node, when evaluated at _runtime_.

(this is a subtle but very important point. if your flow control depends
on request-time conditions, you must do it in the underlying language
layer, not using xslt in the logicsheet. it's easy to mess that up if you
haven't written a logicsheet before, or so i've found.)

so what should your logicsheet do? well, it might help to see what this
page looks like if you apply request.xsl first:

<content>
   <mytaglib1:dosomething>
     <parameter><xsp:expr>
          XSPRequestLibrary.getParameter(
            request,
            String.valueOf("abc"),
            null
          )
        </xsp:expr></parameter>
   </mytaglib1:dosomething>

   <mytaglib2:dosomethingelse>
     <parameter2><xsp:expr>
          XSPRequestLibrary.getParameter(
            request,
            String.valueOf("def"),
            null
          )
        </xsp:expr></parameter2>
   </mytaglib2:dosomethingelse>
</content>

(outer contents removed, of course)

what you could do is simply modify your logicsheet like so:

> <xsl:template match="mytaglib1:dosomething">
>    <xsp:logic>
>    {
>    String xx = <xsl:apply-templates select="parameter"/>;
>    }
>    </xsp:logic>
> </xsl:template>

then you'd end up with

String xx = <xsp:expr>XSPRequestLibrary.getParameter(
            request,
            String.valueOf("abc"),
            null
          )
</xsp:expr>;

when ends up being:

String xx = xspExpr(XSPRequestLibrary.getParameter(
            request,
            String.valueOf("abc"),
            null
          );

which is what you want to have happen. unfortunately, this isn't going to
work if your parameter appears in the xml file as plain text:

<parameter>foo</parameter>

since you'd end up with

String xx = xspExpr(foo);

which is going to break because the string isn't marked up like java needs
it to be. so what get-nested-content is is a template which can accomodate
both of these scenarios:

  <xsl:template name="get-nested-content">
    <xsl:param name="content"/>
        <xsl:choose>
                <xsl:when test="$content/*">
                        <xsl:apply-templates select="$content/*"/>
                </xsl:when>
                <xsl:otherwise>"<xsl:value-of
select="$content"/>"</xsl:otherwise>
        </xsl:choose>
  </xsl:template>

which says, "process the children of the parameter element. if there are
any element children, apply-templates to them and the text children,
otherwise returns the value of the text descendents surrounded by double
quotes."

as it turns out, for the sql logicsheet family, i had to write a modified
version of the method specifically for deeply nested strings:

<xsl:template name="get-nested-string">
        <xsl:param name="content"/>
        <xsl:choose>
                <xsl:when test="$content/*">
                        ""
                        <xsl:for-each select="$content/node()">
                                <xsl:choose>
                                        <xsl:when test="name(.)">
                                                + <xsl:apply-templates
select="."/>
                                        </xsl:when>
                                        <xsl:otherwise>
                                                + "<xsl:value-of
select="translate(.,'&#9;&#10;&#13;','   ')"/>"
                                        </xsl:otherwise>
                                </xsl:choose>
                        </xsl:for-each>
                </xsl:when>
                <xsl:otherwise>"<xsl:value-of
select="normalize-space($content)"/>"</xsl:otherwise>
        </xsl:choose>
</xsl:template>

i can't actually remember the problem that the vanilla get-nested-content
method wasn't able to accomodate, something to do with java being unhappy
with some newlines in the generated source or something.
get-nested-content doesn't place any real constraints on what the child
elements must resolve to at run-time, while get-nested-string forces all
objects to be cast as strings. use what works best for you. bonus points
if you can figure out a good way for the cocoon logicsheets to _share_
these functions instead of replicating them in all of the logicsheets.

one thing to remember when writing logicsheets - you should make it so
that your parameters may be the results from other logicsheets, and so
that your results may be used as parameters by other logicsheets. think
about the result of a big get-nested-string call - it's going to end up
being one big string:

String foo = String xx = "prefix_"+
xspExpr(XSPRequestLibrary.getParameter(
            request,
            String.valueOf(rs.getString(3)),
            null
          )) +
xspExpr(XSPCookieLibrary.getCookie(request,"foo",null)).equals("bar") ? "yes" : "no"
;

your results elements can't have any <xsp:logic> elements underneath
themselves since they'd break up the string, it must be one big
expression. this is sort of what was so problematic with the first sql
logicsheet - i was manually creating some elements and tacking them onto
the result document. i wasn't providing a set of result elements that
could fit nicely into a more elaborate expression. in the esql logicsheet,
however, all of the result-generating elements (get-string, get-date,
get-xml, etc.) are carefully designed to strictly return expressions,
never have logic blocks inside themselves. the only exception is
get-columns, which is provided for a minimal amount of backwards
compatibility and for those who are too lazy to type.

you'll end up with a much more useful logicsheet if you make as few
assumptions as possible about how it's going to be used. again, to use the
esql logicsheet as an example, the main code block consists of
initializing the sql objects and executing the query. if there is data,
whatever actions the page author has put underneath the esql:results
element happen. they can be anything - in my logicsheet, i simply

<xsl:apply-templates select="esql:results/*"/>

similarly, if there is an error, the error-results block is invoked:

<xsl:apply-templates select="esql:error-results/*"/>

now that i'm really starting to ramble, i'll add one more note and
stop. it's important to keep variable scope in mind when you're writing
your logicsheets - you don't want your variables to conflict with those 
of any other logicsheets. so it's friendly of you to surround your logic
elements with curly braces to limit your variables' scope. in addition to
that, i think it would be wise to prepend a signature string onto all of
your variables and methods, e.g. _esql_ or _mail_. yeah, it's cumbersome,
but it's neighborly.

sorry to be so verbose, but this question deserves a long response. hope
it made some sense.

- donald


get-nested-content & get-parameter question

Posted by Chris Meyer <cm...@ultratask.com>.
Hi,

I see the template 'get-nested-content' used all over the place in 
the built-in tag libs... Can someone explain its motivation and use? 
Why is it needed?

I have an XML page and two tag libs (see below). The first tag lib 
works fine. The second one gives me a compile error (in the String 
assignment because the get-parameter name="def" simply substitutes an 
empty string). I'm not using 'get-nested-content'. Should I be? 
Anyone have any ideas why the substitution for get-parameter 
name="def" wouldn't substitute in the same one the other one ("abc") 
substitutes?

Sorry for the complex question -- hopefully someone has seen and 
solved a similar problem...

Chris

------------------------------------
<?xml version="1.0"?>
<?xml-stylesheet href="index.xsl" type="text/xsl"?>
<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>

<xsp:page
   language="java"
   create-session="true"
   xmlns:sql="http://www.apache.org/1999/SQL"
   xmlns:xsp="http://www.apache.org/1999/XSP/Core"
   xmlns:request="http://www.apache.org/1999/XSP/Request"
   xmlns:mytaglib1="http://mystuff.com/mytaglib1"
   xmlns:mytaglib2="http://mystuff.com/mytaglib2"
>

<content>
   <mytaglib1:dosomething>
     <parameter><request:get-parameter name="abc"></parameter>
   </mytaglib1:dosomething>

   <mytaglib2:dosomethingelse>
     <parameter2><request:get-parameter name="def"></parameter2>
   </mytaglib2:dosomethingelse>
</content>
------------------------------------

I also have tag libs that look like this:

------------------------------------
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xsp="http://www.apache.org/1999/XSP/Core"
   xmlns:mytaglib1="http://mystuff.com/mytaglib1"
>

<xsl:template match="xsp:page">
   <xsp:page>
     <xsl:apply-templates select="@*"/>
     <xsl:apply-templates/>
   </xsp:page>
</xsl:template>

<xsl:template match="mytaglib1:dosomething">
   <xsp:logic>
   {
   String xx = <xsl:value-of select="parameter"/>;
   }
   </xsp:logic>
</xsl:template>

<xsl:template match="@*|*|text()|processing-instruction()">
   <xsl:copy>
     <xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>
------------------------------------

and

------------------------------------
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xsp="http://www.apache.org/1999/XSP/Core"
   xmlns:mytaglib2="http://mystuff.com/mytaglib2"
>

<xsl:template match="xsp:page">
   <xsp:page>
     <xsl:apply-templates select="@*"/>
     <xsl:apply-templates/>
   </xsp:page>
</xsl:template>

<xsl:template match="mytaglib2:dosomethingelse">
   <xsp:logic>
   {
   String yy = <xsl:value-of select="parameter2"/>;
   }
   </xsp:logic>
</xsl:template>

<xsl:template match="@*|*|text()|processing-instruction()">
   <xsl:copy>
     <xsl:apply-templates select="@*|*|text()|processing-instruction()"/>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>
------------------------------------