Moddy Te'eni wrote:
Thank you, this is very helpful.


David Bertoni wrote:
Moddy Te'eni wrote:
Thank you very much for your patience.

I'll try to be more thorough this time.

I want to give my users the ability to write XPath expressions that refer
to
some XML input. There is no XSLT involved, just displaying the results.

The user should be abe to use some pre-defined variables: some are
global,
and some depend on the document meta-data and on other things that i am
able
to calculate. For example, i want to user to write "/pers...@name ==
$USERNAME]/@password".

My plan is to use XPathEvaluator::evaluate(), but before calling it I
want
to change the context node so that $USERNAME will be meaningful. Reading
xpath documentaion in w3c, i thought there would be some obvious way to
do
such things.
How variables are bound is not specified in the XPath recommendation, since it's specific to the environment in which XPath is implemented.



It was wishful thinking - that a generic xpath library will have an obvious
way to tell it what the variables are.
Yes, the XPathEvaluator class was written before there were any attempts at standardizing something like XPathEvaluator. It's funny though, because I can't recall previous postings about this in all the years that class has been around.

You might want to create a Jira request for enhancements to the XPathEvaluator class to allow for pluggable variable bindings. It shouldn't be too hard to do.


David Bertoni wrote:

At first I thought I can overcome it by changing the syntax a little and
introducing a function, e.g.

"/pers...@name == env.getValue("USERNAME")]/@password"

But I realized that I can't write this function - my code should be
thread-safe, and each thread may have different users, so there is no way
I
can find the user name, short of using Thread-Local Storage.
I'm afraid I don't understand this. Each thread of execution will need its own instance of XPathEvaluator, so you can extend the classes used by XPathEvaluator to define the correct variable bindings.



You understood very well: If I write an extension function, i need to
implement execute(). The arguments of execute() don't have any way to put
specific information that i need - e.g. in which thread i am. The only way
to pass it is in the XpathExecutionContext, but i can't control it Unless I
change XPathEvaluator.
Actually, there is a way to control this on a per-thread basis. You can install an extension function "locally" into a particular instance of the XPathEnvSupportDefault instance for each XPathEvaluator. That instance of the extension function could contain the necessary value bindings.

However, I think this is more difficult than just creating a derivation of XPathExecutionContextDefault that just knows how to bind the variables you're interested in.



David Bertoni wrote:

You could derive a class from XPathExecutionContextDefault and override getVariable() to handle the specific variables you're interested in resolving. If you get a request for a variable that you don't know about, you can defer to the base class implementation.

Unfortunately, XPathEvaluator is not really meant to be extensible, but we would enhance it for the purposes of extending the execution environment. My recommendation right now would be for you to simply copy the XPathEvaluator code and create your derivative of XPathExecutionContextDefault.



The change in my own version of XPathEvaluator should be as simple as
changing the constractor, isn't it?
Pretty much. You would need to have it create an instance of your XPathExecutionContextDefault derivate and decide how to communicate the variables bindings into each instance of your new XPathEvaluator.

Note you will need to put your "XPathEvaluator" class into a different namespace, or rename to avoid problems with duplicate definitions.

Dave



David Bertoni wrote:

I hope this makes sense, and please reply back if you have more questions.

Another way is, I think, to add things to the DOM instead of variables.
then
the user may write

"/pers...@name == /envValues/@USERNAME)]/@password"

This is ugly, though. So I still hope I can avoid it.
Yes, that would be ugly, and would require a unique copy of the source tree for each user.

Dave




Thanks again, Moddy.

Reply via email to