Dimitri, <snip> > > Hmmm. This seems a bit strange to me. It works for Maps (using put instead > > of add). > Sure, a Map is not a Collection. >
Good point. :) <snip> > > So you can see that the Map is mutable. I'm not sure how difficult it is > to > > allow for mutable Lists, but if I can't do things like: > > > > getValue("list:add($myList, 'hello')") returns: true > > > There is a sort-of round about way of getting to a list by reference. > Create a wrapper for it and pass that wrapper to your own custom extension > function, which would then add an element to the list. Yes, that is a possibility. > > > I think it might be a show stopper for me. I am almost certainly trying to > > use JXPath in a way that was not intended. I am trying to build a 2 way > data > > binding mapping structure which I think JXPath is excellent for, but I > would > > also like to add some easy micro-scripting, which is maybe not possible > with > > JXPath. > Right, I think you might be stretching JXPath's capabilities. The > getValue() method is supposed to be a query, that is a request without side > effects. Thought so. However, it would make it a very cool tool indeed if it could be used like that, no? It seems that JXPath is very close to allowing me to do this. > > > One other thing, can you explain to me why the returned collections should > > be immutable? Is it necessary to enforce that behaviour? > I make the collection immutable simply to get it to throw an exception. If > the collection is mutable, operations changing it are successful, but since > the changes are made to some temporary collection, not the original one you > want to change. I understand that if you are performing a query or a slice or something (within an XPath) that you must have to create a temporary collection to hold the result, however I still don't see why, if you are referencing a whole collection (i.e. $myList), a copy is made before operating on it. I still don't see the fundemental difference between this: getValue("map:put($myMap, 'key', 'value')") returns: null which calls 'put' on my original Map: and this: getValue("list:add($myList, 'hello')") returns: true which calls 'add' on a temporary copy of my original list, Why do we create a temporary structure just because the target of the ExtensionFunction is a Collection? Is it just because of the implementation details, or is it by design? Sorry for being a pain! :) BTW - I have hacked a patch that allows XPaths like this: context.createPathAndSetValue("$myList[-1]", "'hello'"); which now adds to the List. I had to do this because when I tried this: context.createPathAndSetValue("$myList[last()+1]", "'hello'"); I got an exception: org.apache.commons.jxpath.JXPathException: Cannot set value for xpath: $myList[last()+1] at org.apache.commons.jxpath.ri.JXPathContextReferenceImpl.setValue(JXPathConte xtReferenceImpl.java:412) I would have expected that my Factory would have been invoked in order to expand the List, but it never got called. Cheers, Adam. > > > Thanks for your help, > > > > > Adam. > > I hope this does not make jxpath completely unusable for you. > > - Dmitri > > > > > > > > > > ----- Original Message ----- > > From: "Dmitri Plotnikov" <[EMAIL PROTECTED]> > > To: "Jakarta Commons Developers List" <[EMAIL PROTECTED]> > > Sent: Thursday, February 06, 2003 9:47 PM > > Subject: Re: [JXPath] Problem adding objects to an ArrayList Variable > > > > > > > Adam, > > > > > > JXPath is in fact incapable of doing what you want it to do. Before a > > > collection is passed to an extension function, it undergoes some > > > conversions, which make it unmodifiable. JXPath should of course throw > > > an exception in this case. I have added that exception and will check > > > that new code in tonight. > > > > > > The rationale for this behavior is that from JXPath's perspective an > > > extension function cannot take a collection by reference. Arguments of > > > an extension function are either primitive values or "node sets", which > > > are really results of search. JXPath finds all nodes matching the > > > path, loads them into a list and then passes the list to the function. > > > Consider for example this: > > > > > > context.getValue("size(//foo[bar = 3])") > > > > > > From this example it should be clear that the argument of the function > > > is in fact an unmodifiable collection - results of search. > > > > > > We could of course do something special for variables, but then the > > > extension function's code would have to be aware of the difference > > > between variables and general node sets. I think we should avoid this > > > implicit difference. > > > > > > What you could do to add a node to the collection is call > > > createPathAndSetValue() with a path like "$myList[24]". > > > > > > Thanks for bringing this issue up - I should document it. > > > > > > - Dmitri > > > > > > > > > --- Adam J Chesney <[EMAIL PROTECTED]> wrote: > > > > Hi, > > > > > > > > Attached is a small test program that simply defines a Context like > > > > this: > > > > > > > > Object o = new Object (); > > > > JXPathContext context = JXPathContext.newContext( o ); > > > > context.getVariables().declareVariable("myList", new ArrayList() ); > > > > > > > > FunctionLibrary library = new FunctionLibrary (); > > > > library.addFunctions( new ClassFunctions ( List.class, "list" ) ); > > > > context.setFunctions( library ); > > > > > > > > The output from executing several XPath expressions on it is thus: > > > > > > > > getValue("list:size($myList)") returns: 0 > > > > > > > > getValue("list:add($myList, 'hello')") returns: true > > > > > > > > getValue("list:size($myList)") returns: 0 > > > > > > > > getValue("$myList") returns: [] > > > > > > > > I would expect the String 'hello' to be added to the list, and > > > > therefore the second call to size should return 1. > > > > > > > > Am I doing something wrong here? > > > > > > > > Cheers, > > > > > > > > Adam > > > > > > > > ===================================================== > > > > > > > > Tel: (+44) 117 908 1254 (Direct) > > > > Mobile (+44) 7780 962 961 > > > > email: [EMAIL PROTECTED] > > > > > > > > This communication is intended solely for the addressee and is > > > > confidential. > > > > If you are not the intended recipient, any disclosure, copying, > > > > distribution > > > > or any action taken or omitted to be taken in reliance on it, is > > > > prohibited > > > > and may be unlawful. > > > > > > > > Although this e-mail and any attachments are believed to be free of > > > > any > > > > virus, or any other defect which might affect any computer or IT > > > > system into > > > > which they are received and opened, it is the responsibility of the > > > > recipient to ensure that they are virus free and no responsibility is > > > > accepted by Multicom Products Limited for any loss or damage arising > > > > in any > > > > way from receipt or use thereof. > > > > > package test; > > > > > > > > import org.apache.commons.jxpath.*; > > > > import java.util.*; > > > > > > > > /** > > > > * <p>Title: </p> > > > > * <p>Description: </p> > > > > * <p>Copyright: Copyright (c) 2003</p> > > > > * <p>Company: </p> > > > > * @author unascribed > > > > * @version 1.0 > > > > */ > > > > > > > > public class Test2 > > > > { > > > > > > > > public static void main(String[] args) > > > > { > > > > try > > > > { > > > > Object o = new Object (); > > > > JXPathContext context = JXPathContext.newContext( o ); > > > > context.getVariables().declareVariable("myList", new ArrayList() ); > > > > > > > > FunctionLibrary library = new FunctionLibrary (); > > > > library.addFunctions( new ClassFunctions ( List.class, "list" ) ); > > > > context.setFunctions( library ); > > > > > > > > getValue (context, "list:size($myList)"); > > > > getValue (context, "list:add($myList, 'hello')"); > > > > getValue (context, "list:size($myList)"); > > > > getValue (context, "$myList"); > > > > } > > > > catch (Exception e1) > > > > { > > > > e1.printStackTrace(); > > > > } > > > > } > > > > > > > > public static Object getValue ( JXPathContext context, String xpath > > > > ) > > > > { > > > > Object obj = context.getValue( xpath ); > > > > System.out.println("getValue(\"" + xpath + "\") returns: " + obj > > > > ); > > > > return obj; > > > > } > > > > > > > > } > > > > > > > > --------------------------------------------------------------------- > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > __________________________________________________ > > > Do you Yahoo!? > > > Yahoo! Mail Plus - Powerful. Affordable. Sign up now. > > > http://mailplus.yahoo.com > > > > > > --------------------------------------------------------------------- > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > -------------------------------------------------------------------------- -- > ---- > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]