2 // Mono.Xml.XPath.LocationPathPattern
5 // Ben Maurer (bmaurer@users.sourceforge.net)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System
.Collections
;
35 using System
.Xml
.Schema
;
36 using System
.Xml
.XPath
;
39 namespace Mono
.Xml
.XPath
{
40 internal class LocationPathPattern
: Pattern
{
42 LocationPathPattern patternPrevious
;
46 XPathNavigator previousNavigator
;
48 public LocationPathPattern (NodeTest nodeTest
)
50 this.nodeTest
= nodeTest
;
53 public LocationPathPattern (ExprFilter filter
)
57 while (! (filter
.expr
is NodeTest
))
58 filter
= (ExprFilter
)filter
.expr
;
60 this.nodeTest
= (NodeTest
)filter
.expr
;
63 internal void SetPreviousPattern (Pattern prev
, bool isAncestor
)
65 LocationPathPattern toSet
= LastPathPattern
;
66 toSet
.patternPrevious
= (LocationPathPattern
)prev
;
67 toSet
.isAncestor
= isAncestor
;
70 public override double DefaultPriority
{
72 if (patternPrevious
== null && filter
== null) {
73 NodeNameTest t
= nodeTest
as NodeNameTest
;
75 if (t
.Name
.Name
== "*")
86 public override bool Matches (XPathNavigator node
, XsltContext ctx
)
88 if (! nodeTest
.Match (ctx
, node
))
91 if (nodeTest
is NodeTypeTest
) {
92 // node () is different in xslt patterns
93 if (((NodeTypeTest
)nodeTest
).type
== XPathNodeType
.All
&&
94 (node
.NodeType
== XPathNodeType
.Root
||
95 node
.NodeType
== XPathNodeType
.Attribute
)
100 if (filter
== null && patternPrevious
== null)
103 if (patternPrevious
!= null) {
105 XPathNavigator parent
= node
.Clone ();
106 parent
.MoveToParent ();
107 if (!patternPrevious
.Matches (parent
, ctx
))
110 XPathNavigator anc
= node
.Clone ();
112 if (!anc
.MoveToParent ())
115 if (patternPrevious
.Matches (anc
, ctx
))
125 // Optimization for non-positional predicate
126 if (!filter
.IsPositional
&& !(filter
.expr
is ExprFilter
)) {
127 return filter
.pred
.EvaluateBoolean (new NullIterator (node
, ctx
));
130 XPathNavigator p
= null;
131 if (previousNavigator
== node
) {
132 p
= previousNavigator
;
136 previousNavigator
= p
;
140 BaseIterator matches
= filter
.EvaluateNodeSet (new NullIterator (p
, ctx
));
142 while (matches
.MoveNext ()) {
143 if (node
.IsSamePosition (matches
.Current
))
150 public override string ToString ()
153 if (patternPrevious
!= null) ret
= patternPrevious
.ToString () + (isAncestor
? "//" : "/");
154 if (filter
!= null) ret
+= filter
.ToString ();
155 else ret
+= nodeTest
.ToString ();
160 public LocationPathPattern LastPathPattern
{
162 LocationPathPattern ret
= this;
164 while (ret
.patternPrevious
!= null)
165 ret
= ret
.patternPrevious
;