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;
40 namespace Mono.Xml.XPath {
41 internal class LocationPathPattern : Pattern {
43 LocationPathPattern patternPrevious;
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 == "*" || t.Name.Name.Length == 0)
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 XPathNavigator tmpNav;
104 if (patternPrevious != null) {
105 tmpNav = ((XsltCompiledContext) ctx).GetNavCache (this, node);
107 tmpNav.MoveToParent ();
108 if (!patternPrevious.Matches (tmpNav, ctx))
112 if (!tmpNav.MoveToParent ())
115 if (patternPrevious.Matches (tmpNav, 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 tmpNav = ((XsltCompiledContext) ctx).GetNavCache (this, node);
131 tmpNav.MoveToParent ();
133 BaseIterator matches = filter.EvaluateNodeSet (new NullIterator (tmpNav, ctx));
135 while (matches.MoveNext ()) {
136 if (node.IsSamePosition (matches.Current))
143 public override string ToString ()
146 if (patternPrevious != null) ret = patternPrevious.ToString () + (isAncestor ? "//" : "/");
147 if (filter != null) ret += filter.ToString ();
148 else ret += nodeTest.ToString ();
153 public LocationPathPattern LastPathPattern {
155 LocationPathPattern ret = this;
157 while (ret.patternPrevious != null)
158 ret = ret.patternPrevious;