You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cocoon.apache.org by Ben Pope <no...@hotmail.com> on 2004/08/12 22:35:00 UTC

Cforms, Binding cross-referenced data

Hi,

I'm trying to bind some data in a form, the data looks like this:

<project>
   <people>
      <person id="0">
         <name>Me</name>
      </person>
      <person id="1">
         <name>You</name>
      </person>
      <person id="2">
         <name>Him</name>
      </person>
   </people>
   <rooms>
      <room id="0">
         <name>Lounge</name>
         <person idref="0"/>
         <person idref="1"/>
      </room>
      <room id="1">
         <name>Kitchen</name>
         <person idref="2"/>
      </room>
   </rooms>
</project>

The idea is that "Me" and "You" are in the "Lounge" and "Him" is in the
kitchen.

Now, I need to be able to bring up a repeater over all the people in a
specific room, and be able to modify the person data using that repeater.
My binding file has taken on various incarnations including this one:

<fb:context xmlns:fb="http://apache.org/cocoon/forms/1.0#binding"
path="/project">
   <fb:value id="roomName"/><!-- @path is dynamic -->
   <fb:repeater id="people"><!--  @parent-path & @row-path are dynamic-->
      <fb:identity>
         <fb:value id="id" path="@idref">
            <fd:convertor datatype="long"/>
         </fb:value>
      </fb:identity>
      <fb:on-bind>
         <fb:value id="personName"/><!-- @path is dynamic -->
      </fb:on-bind>
      <fb:on-insert-row>
         <fb:insert-node>
            <person idref=""/>
         </fb:insert-node>
      </fb:on-insert-row>
      <fb:on-delete-row>
         <fb:delete-node/>
      </fb:on-delete-row>
   </fb:repeater>
</fb:context>


Which is transformed as follows to allow the room to be dynamically selected
with a URI like:
/test/form?room=0


<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:fb="http://apache.org/cocoon/forms/1.0#binding">

   <xsl:param name="room"/>
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

   <xsl:template match="/fb:context/fb:value[@id='roomName']">
      <fb:value id="roomName" path="rooms/room[@id={$room}]/name"/>
   </xsl:template>

   <xsl:template match="/fb:context/fb:repeater[@id='people']">
      <fb:repeater id="people" parent-path="rooms/room[@id={$room}]"
row-path="person">
         <xsl:apply-templates/>
      </fb:repeater>
   </xsl:template>

   <xsl:template
match="/fb:context/fb:repeater[@id='people']/fb:on-bind/fb:value[@id='person
Name']">
      <fb:value id="personName"
path="/project/people/person[@id=current()/@idref]"/> 
   </xsl:template>

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:transform>


Now, I think that's roughly how I want it to work, but:
"org.apache.commons.jxpath.JXPathException: Undefined function: current"

OK, anybody know how I use the XSLT currect() function from here?


An alternative that I toyed with involved replacing the definition of the
repeater with:

<fb:repeater id="people" parent-path="rooms/room[@id={$room}]"
 
row-path="/project/people/person[@id=/project/rooms/room[@id={$room}]/person
/@idref]">

(and adjusting the personName path to just "name")

Which is fine, but then whenever I delete or add a row, I delete the actual
person, rather than the reference to the person in the room, since the
repeater is effectively over the people/person rather than the room/person
references.

Now that could be workable, I guess I'd have to write custom add and remove
row functions, but I would rather not (or is that a bad move?)


Instead of using the "current()" function, I've tried an Xpath for the
person/name binding that looks like this:

<fb:value id="personName"
path="/project/people/person[@id=/project/rooms/room[@id={$room}]/person/@id
ref]/name"/>

But that just seems to select the first person/name referenced from the
room/person - I feel like I want to be using the current() function again to
get the correct id/idref.

Anybody know how to get the current() function working, or another solution
to the problem?

Thanks for your time.
Ben.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@cocoon.apache.org
For additional commands, e-mail: users-help@cocoon.apache.org