You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-users@xalan.apache.org by Moddy Te'eni <mt...@informatica.com> on 2009/02/04 03:51:06 UTC

creating variables for XPath

Is there a way to create variables in C++, same as in Xalan-J
XPathVariableResolver?



-- 
View this message in context: http://www.nabble.com/creating-variables-for-XPath-tp21823462p21823462.html
Sent from the Xalan - C - Users mailing list archive at Nabble.com.


Re: creating variables for XPath

Posted by David Bertoni <db...@apache.org>.
Moddy Te'eni wrote:
> Meanwhile, I had another idea. I don't manage to implement it without
> crashing, though. Probably because I can't find any documentation.
> 
> I avoid using XPathEvaluator, but instead use XPath::execute. This is a code
> snippet, which i inserted in the SimpleXPathApi sample code
If you follow the model of XPathEvaluator, you shouldn't have any problems.

> 
> 
> 
>> 		// Parse the document...
>> 		XalanDocument* const	theDocument =
>> 				theLiaison.parseXMLStream(theInputSource);
>> 		assert(theDocument != 0);
>>
>> 		XalanDocumentPrefixResolver		thePrefixResolver(theDocument);
>>
>> 		XPathProcessorImpl theProcessor;
>> 		XPathConstructionContextDefault theConstructionContext;
>>
>>
>> 		XPathExecutionContextDefault theExecutionContext(
>> XalanMemMgrs::getDefault());
>>
>> 		XPath root(XalanMemMgrs::getDefault());
>> 		theProcessor.initXPath(root, theConstructionContext,
>> XalanDOMString(argv[3]), thePrefixResolver);
>>
>>
>> 		// OK, let's find the context node...
>> 		const XObjectPtr& 	theResult =
>> 			root.execute(theDocument, thePrefixResolver, theExecutionContext);
>>
>>
> 
> Later I will change XPathExecutionContextDefault to my own class, but
> meanwhile this program crashes in execute(), and I can't see why.
Without a copy of your instance document and the actual arguments to 
your application, it's hard to say what my be going wrong.

Dave

Re: creating variables for XPath

Posted by Moddy Te'eni <mt...@informatica.com>.
Meanwhile, I had another idea. I don't manage to implement it without
crashing, though. Probably because I can't find any documentation.

I avoid using XPathEvaluator, but instead use XPath::execute. This is a code
snippet, which i inserted in the SimpleXPathApi sample code



> 		// Parse the document...
> 		XalanDocument* const	theDocument =
> 				theLiaison.parseXMLStream(theInputSource);
> 		assert(theDocument != 0);
> 
> 		XalanDocumentPrefixResolver		thePrefixResolver(theDocument);
> 
> 		XPathProcessorImpl theProcessor;
> 		XPathConstructionContextDefault theConstructionContext;
> 
> 
> 		XPathExecutionContextDefault theExecutionContext(
> XalanMemMgrs::getDefault());
> 
> 		XPath root(XalanMemMgrs::getDefault());
> 		theProcessor.initXPath(root, theConstructionContext,
> XalanDOMString(argv[3]), thePrefixResolver);
> 
> 
> 		// OK, let's find the context node...
> 		const XObjectPtr& 	theResult =
> 			root.execute(theDocument, thePrefixResolver, theExecutionContext);
> 
> 

Later I will change XPathExecutionContextDefault to my own class, but
meanwhile this program crashes in execute(), and I can't see why.

Moddy
-- 
View this message in context: http://www.nabble.com/creating-variables-for-XPath-tp21823462p22176711.html
Sent from the Xalan - C - Users mailing list archive at Nabble.com.


Re: creating variables for XPath

Posted by David Bertoni <db...@apache.org>.
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 "/Person[@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.
>>>
>>> "/Person[@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
>>>
>>> "/Person[@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.


Re: creating variables for XPath

Posted by Moddy Te'eni <mt...@informatica.com>.
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 "/Person[@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. 

David Bertoni wrote:
> 
> 
>> At first I thought I can overcome it by changing the syntax a little and
>> introducing a function, e.g.
>> 
>> "/Person[@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.


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?


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
>> 
>> "/Person[@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.
-- 
View this message in context: http://www.nabble.com/creating-variables-for-XPath-tp21823462p22175054.html
Sent from the Xalan - C - Users mailing list archive at Nabble.com.


Re: creating variables for XPath

Posted by David Bertoni <db...@apache.org>.
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 "/Person[@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.

> 
> At first I thought I can overcome it by changing the syntax a little and
> introducing a function, e.g.
> 
> "/Person[@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.

Let me explain a bit about how variable binding works in Xalan-C, and 
hopefully you can figure out how you need to implement it in your 
environment.

There is an abstract base class, called XPathExecutionContext that 
defines much of the run-time environment requirements for executing 
XPath expressions.  The member function 
XPathExecutionContext::getVariable() can be implemented to define 
variable bindings.  If you look at the default implementation of this 
base class, called XPathExecutionContextDefault, you'll see it returns 
an "unknown" object, since the default implementation doesn't know 
anything about variable binding.  AS another point of reference, if you 
look at the version of this function in 
StylesheetExecutionContexDefault, you'll see it uses the XSLT variables 
stack to resolve variables.

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.

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
> 
> "/Person[@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

Re: creating variables for XPath

Posted by Moddy Te'eni <mt...@informatica.com>.
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 "/Person[@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.

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

"/Person[@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.

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

"/Person[@name == /envValues/@USERNAME)]/@password"

This is ugly, though. So I still hope I can avoid it.

Thanks, Moddy.





David Bertoni-2 wrote:
> 
> On Fri, Feb 6, 2009 at 1:40 AM, Moddy Te'eni <mt...@informatica.com>
> wrote:
> 
>>
>> Ah, So I got it wrong.
>>
>> Anyway, what I'm looking for is a way to set user-defined variables. I
>> don't
>> see any API that creates them, accept by using XSLT.
> 
> Yes, there are APIs that do that, depending on the context.  For example,
> user-installed functions can create variables, which you can see by
> looking
> at the implementations of the EXSLT functions in src/xalac/XalanEXSLT.
> 
> If examining the source code for those functions doesn't answer your
> question, please be more specific about what you're trying to do.
> 
> Dave
> 
> 

-- 
View this message in context: http://www.nabble.com/creating-variables-for-XPath-tp21823462p22154274.html
Sent from the Xalan - C - Users mailing list archive at Nabble.com.


Re: creating variables for XPath

Posted by David Bertoni <db...@gmail.com>.
On Fri, Feb 6, 2009 at 1:40 AM, Moddy Te'eni <mt...@informatica.com> wrote:

>
> Ah, So I got it wrong.
>
> Anyway, what I'm looking for is a way to set user-defined variables. I
> don't
> see any API that creates them, accept by using XSLT.

Yes, there are APIs that do that, depending on the context.  For example,
user-installed functions can create variables, which you can see by looking
at the implementations of the EXSLT functions in src/xalac/XalanEXSLT.

If examining the source code for those functions doesn't answer your
question, please be more specific about what you're trying to do.

Dave

Re: creating variables for XPath

Posted by Moddy Te'eni <mt...@informatica.com>.
Ah, So I got it wrong.

Anyway, what I'm looking for is a way to set user-defined variables. I don't
see any API that creates them, accept by using XSLT.

Moddy.


David Bertoni-2 wrote:
> 
> On Tue, Feb 3, 2009 at 9:51 PM, Moddy Te'eni <mt...@informatica.com>
> wrote:
> 
>>
>> Is there a way to create variables in C++, same as in Xalan-J
>> XPathVariableResolver?
> 
> As far as I can tell, XPathVariableResolver doesn't create variables -- it
> resolves a QName to a variable value.
> 
> Can you be more specific about what you are trying to do?
> 
> Dave
> 
> 

-- 
View this message in context: http://www.nabble.com/creating-variables-for-XPath-tp21823462p21867394.html
Sent from the Xalan - C - Users mailing list archive at Nabble.com.


Re: creating variables for XPath

Posted by David Bertoni <db...@gmail.com>.
On Tue, Feb 3, 2009 at 9:51 PM, Moddy Te'eni <mt...@informatica.com> wrote:

>
> Is there a way to create variables in C++, same as in Xalan-J
> XPathVariableResolver?

As far as I can tell, XPathVariableResolver doesn't create variables -- it
resolves a QName to a variable value.

Can you be more specific about what you are trying to do?

Dave