Re: Accessing Transformiix library from C++
"David Landwehr" <[email protected]>
| Newsgroups | gmane.comp.mozilla.devel.layout.xslt |
|---|---|
| Organization | Another Netscape Collabra Server User |
| Message-ID | <[email protected]> |
Subject: Analyzing the XPath expressions in XForms
The master dependency graph in XForms requires knowledge about what nodes an XPath expression is dependent on. During the xforms-rebuild phase all model item properties [mip] are analyzed with respect to a context node. This context node has a dependency to all the nodes which the mip depend on. Following is an example:
Instance:
<a @value="1"/>
Bind:
<xforms:bind nodeset="/a" relevant="@value=1"/>
In this case the node <a/> is dependent on the nodes from the 'relevant' property which is the @value attribute. This means that whenever @value is changed the relevant expression must be reevaluated.
Analyzing an XPath expression is not as trivial as one might expect, because changes to the instance might change the dependencies for an expression. An example:
Instance:
<a>
<b value='0'>1</b>
<b value='1'>2</b>
</a>
Bind:
<xforms:bind nodeset="a" relevant="b[@value='1']=2"/>
If the b/@value='0' is changed of b/@value='1' after the rebuild then the calculations should still be correct and if b[1] is changed to 2 then the relevant mip should be reevaluated. The implications of this is that when analyzing the expression predicates should be disregarded, however still analyzed. So <a/> has dependencies upon the following nodeset {b[1], b[2], b[1]/@value, b[2]/@value}.
There are a couple of ways to analyze the expression:
1) In the IE plugin we use an XPath expression analyzer which breaks up the XPath expression.
2) In the java processor we use an XPath engine in a special mode to find the nodes.
What 1) does is to break up all axis an expression consists of and makes an evaluation hierarchy of that. An example is the following:
Expression /a/b[@value='1']/c | /a/c[@value='1']/c
/a/b
| @value
| c
/a/c
| @value
| c
When making the analysis each step is evaluated as an XPath expression. If the expression is a child then it is evaluated for each node collected by the parent expression.
What 2) does is to collect nodes during evaluations but in such a way that even nodes that fails a predicate is still taken into consideration when evaluating the following axis step. Therefore the result of an analyzed expression is different from actually running the expression.
Best regards,
David
----------------------------------------------------------------
David Landwehr [email protected]
Novell, Inc. Phone: +45 33 98 15 04
Amaliegade 16C Fax: +45 70 20 15 17
DK-1256 Copenhagen K http://www.novell.com
----------------------------------------------------------------
>>> Axel Hecht<[email protected]> 09/20/04 5:57 pm >>>
Axel Hecht wrote:
> Allan Beaufour wrote:
>
>> Peter Van der Beken wrote:
>>
>>> Allan Beaufour wrote:
>>>
>>>> Axel Hecht wrote:
>>>>
>>>>> You can use DOM Level 3 XPath, esp nsIDOMXPathEvaluator, which is
>>>>> implemented by html and xml documents. See that interface and its
>>>>> friends over in mozilla/dom/public/idl/xpath
>>>>
>>>>
>>>>
>>>> I know. I am aware that I need to access it directly. I am already
>>>> using the "normal" and exposed API for other things.
>>>
>>>
>>>
>>> Why do you need the lexer specifically?
>>
>>
>>
>> I need two things:
>> 1) Get "dynamic function usage" in an expression
>>
>> That is, find out whether and expression has any functions in it that
>> would change the result from call to call, e.g. "now()".
>>
>> 2) Get all nodes that an expression depends on
>>
>> That is all nodes that influences the expression, not the node set
>> returned from an Evaluate(). I need to know that "thing[at=../other +
>> ../another]" depends on "../other" and "../another" (and "thing" of
>> course).
>>
>> The first one is fairly easy done with the lexer. The second one is
>> more tricky, and could probably be done more easily done by
>> instrumenting one or more evaluate()-functions?
>
>
> So, what you need is something like the stuff that Jonas implemented in
> his xpath optim patch. I wonder if you could go for a few simple kinds
> of dependencies / or-all-of-the-doc. And get that exported to XPCOM.
>
> Anyway, we should know how often you need this optimization, and for
> what. Right now, this looks like "it would be simple for me if we had
> this", but this should balance in total.
> These requirements smell like "check if I have to reevaluate if a doc
> changes". How often does that happen? And, is this a validation thing or
> do you need to display up-to-date results of an xpath expression only?
So Allan directed me a bit closer to what's required, and it seems to
boil down to this:
What XForms wants is a list of nodes that can have impact on the result
of an expression. It uses that to determine the order in which to
evaluate expressions, and to detect loops in those dependencies (which
throws an error).
Now the dependency for an expression like
"instance('orderform')/shipTo/firstName"
(http://www.w3.org/TR/xforms/slice7.html#fn-instance) adds the
instance('orderform'), all shipTos and all firstNames. Predicates make
this even more tricky. As you have to evaluate all the nodeset
expressions there, at least.
IIRC, changes to the instance DOM that would add new nodes to the
requirements are said to be recalculating the deps as well, so adding a
shipTo node, or adding a node that fulfills a predicate. I bet we should
have a list of those actions here.
Anyway, what we need to evaluate is the codesize impact of the
alternative methods, and their efficiency.
I see two main routes,
1. XForms uses an xpcom XPath component (like transformiix)
2. XForms ships its own XPath engine, and does not depend on external
code to implement the infrastructure.
The first one gives a smaller download size and is probably easier in
terms of bridging data between mozilla and the xpath engine, the second
one may be easier to adapt to the requirements of XForms.
Why would adaption be hard? Because of the codesize impact. That is
Firefox download size we're talking about here. So we should understand
what that means and how expensive that is. And then we need to think
about how performant.
Give rise to ways 1.a and 1.b.
1.a nsPIXPathXFormsFriend
This way, transformiix would implement interfaces that would compute the
data needed by XForms on its internal datastructures. This is likely
more code and more efficient than 1.b, and it's harder to maintain.
2.b expression inspection
This way, transformiix expression implement interfaces that allow one to
look at steps, predicates and all that, evaluate parts of them with
given contexts, all in xpcom. This is still quite a bit of code.
I'm really not too sure, which one I would prefer. If we could get
patches for both and make up our mind afterwards? Evil.
Axel