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.