1 // Author: Dwivedi, Ajay kumar
\r
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 using System.Collections;
\r
26 using System.Xml.Serialization;
\r
27 using System.ComponentModel;
\r
30 using Mono.Xml.Schema;
\r
32 namespace System.Xml.Schema
\r
35 /// Summary description for XmlSchemaXPath.
\r
37 public class XmlSchemaXPath : XmlSchemaAnnotated
\r
39 private string xpath;
\r
40 XmlNamespaceManager nsmgr;
\r
41 internal bool isSelector;
\r
42 XsdIdentityPath [] compiledExpression;
\r
44 XsdIdentityPath currentPath;
\r
46 public XmlSchemaXPath()
\r
50 [System.Xml.Serialization.XmlAttribute("xpath")]
\r
51 public string XPath
\r
53 get{ return xpath; }
\r
54 set{ xpath = value; }
\r
57 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
\r
59 // If this is already compiled this time, simply skip.
\r
60 if (CompilationId == schema.CompilationId)
\r
63 if (nsmgr == null) {
\r
64 nsmgr = new XmlNamespaceManager (new NameTable ());
\r
65 if (Namespaces != null)
\r
66 foreach (XmlQualifiedName qname in Namespaces.ToArray ())
\r
67 nsmgr.AddNamespace (qname.Name, qname.Namespace);
\r
70 currentPath = new XsdIdentityPath ();
\r
71 ParseExpression (xpath, h, schema);
\r
73 XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);
\r
74 this.CompilationId = schema.CompilationId;
\r
78 internal XsdIdentityPath [] CompiledExpression {
\r
79 get { return compiledExpression; }
\r
82 private void ParseExpression (string xpath, ValidationEventHandler h, XmlSchema schema)
\r
84 ArrayList paths = new ArrayList ();
\r
85 ParsePath (xpath, 0, paths, h, schema);
\r
86 this.compiledExpression = (XsdIdentityPath []) paths.ToArray (typeof (XsdIdentityPath));
\r
89 private void ParsePath (string xpath, int pos, ArrayList paths,
\r
90 ValidationEventHandler h, XmlSchema schema)
\r
92 pos = SkipWhitespace (xpath, pos);
\r
93 if (xpath.Length >= pos + 3 && xpath [pos] == '.') {
\r
96 pos = SkipWhitespace (xpath, pos);
\r
97 if (xpath.Length > pos + 2 && xpath.IndexOf ("//", pos, 2) == pos) {
\r
98 currentPath.Descendants = true;
\r
102 pos = tmp; // revert
\r
104 ArrayList al = new ArrayList ();
\r
105 ParseStep (xpath, pos, al, paths, h, schema);
\r
108 private void ParseStep (string xpath, int pos, ArrayList steps,
\r
109 ArrayList paths, ValidationEventHandler h, XmlSchema schema)
\r
111 pos = SkipWhitespace (xpath, pos);
\r
112 if (xpath.Length == pos) {
\r
113 error (h, "Empty xpath expression is specified");
\r
117 XsdIdentityStep step = new XsdIdentityStep ();
\r
118 switch (xpath [pos]) {
\r
121 error (h, "Selector cannot include attribute axes.");
\r
122 currentPath = null;
\r
126 step.IsAttribute = true;
\r
127 pos = SkipWhitespace (xpath, pos);
\r
128 if (xpath.Length > pos && xpath [pos] == '*') {
\r
130 step.IsAnyName = true;
\r
135 pos++; // do nothing ;-)
\r
136 step.IsCurrent = true;
\r
140 step.IsAnyName = true;
\r
143 if (xpath.Length > pos + 5 && xpath.IndexOf ("child", pos, 5) == pos) {
\r
146 pos = SkipWhitespace (xpath, pos);
\r
147 if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
\r
149 if (xpath.Length > pos && xpath [pos] == '*') {
\r
151 step.IsAnyName = true;
\r
154 pos = SkipWhitespace (xpath, pos);
\r
161 if (xpath.Length > pos + 9 && xpath.IndexOf ("attribute", pos, 9) == pos) {
\r
164 pos = SkipWhitespace (xpath, pos);
\r
165 if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
\r
167 error (h, "Selector cannot include attribute axes.");
\r
168 currentPath = null;
\r
172 step.IsAttribute = true;
\r
173 if (xpath.Length > pos && xpath [pos] == '*') {
\r
175 step.IsAnyName = true;
\r
178 pos = SkipWhitespace (xpath, pos);
\r
185 int nameStart = pos;
\r
186 while (xpath.Length > pos) {
\r
187 if (!XmlChar.IsNCNameChar (xpath [pos]))
\r
192 if (pos == nameStart) {
\r
193 error (h, "Invalid path format for a field.");
\r
194 this.currentPath = null;
\r
197 if (xpath.Length == pos || xpath [pos] != ':')
\r
198 step.Name = xpath.Substring (nameStart, pos - nameStart);
\r
200 string prefix = xpath.Substring (nameStart, pos - nameStart);
\r
202 if (xpath.Length > pos && xpath [pos] == '*') {
\r
203 string ns = nsmgr.LookupNamespace (prefix, false);
\r
205 error (h, "Specified prefix '" + prefix + "' is not declared.");
\r
206 this.currentPath = null;
\r
212 int localNameStart = pos;
\r
213 while (xpath.Length > pos) {
\r
214 if (!XmlChar.IsNCNameChar (xpath [pos]))
\r
219 step.Name = xpath.Substring (localNameStart, pos - localNameStart);
\r
220 string ns = nsmgr.LookupNamespace (prefix, false);
\r
222 error (h, "Specified prefix '" + prefix + "' is not declared.");
\r
223 this.currentPath = null;
\r
226 step.Namespace = ns;
\r
231 if (!step.IsCurrent) // Current step is meaningless, other than its representation.
\r
233 pos = SkipWhitespace (xpath, pos);
\r
234 if (xpath.Length == pos) {
\r
235 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
236 paths.Add (currentPath);
\r
239 else if (xpath [pos] == '/') {
\r
241 if (step.IsAttribute) {
\r
242 error (h, "Unexpected xpath token after Attribute NameTest.");
\r
243 this.currentPath = null;
\r
246 this.ParseStep (xpath, pos, steps, paths, h, schema);
\r
247 if (currentPath == null) // For ValidationEventHandler
\r
249 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
250 } else if (xpath [pos] == '|') {
\r
252 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
253 paths.Add (this.currentPath);
\r
254 this.currentPath = new XsdIdentityPath ();
\r
255 this.ParsePath (xpath, pos, paths, h, schema);
\r
257 error (h, "Unexpected xpath token after NameTest.");
\r
258 this.currentPath = null;
\r
263 private int SkipWhitespace (string xpath, int pos)
\r
266 while (loop && xpath.Length > pos) {
\r
267 switch (xpath [pos]) {
\r
284 // xpath = a subset of XPath expression, see below
\r
285 // {any attributes with non-schema namespace . . .}>
\r
286 // Content: (annotation?)
\r
288 internal static XmlSchemaXPath Read(XmlSchemaReader reader, ValidationEventHandler h,string name)
\r
290 XmlSchemaXPath path = new XmlSchemaXPath();
\r
291 reader.MoveToElement();
\r
293 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != name)
\r
295 error(h,"Should not happen :1: XmlSchemaComplexContentRestriction.Read, name="+reader.Name,null);
\r
300 path.LineNumber = reader.LineNumber;
\r
301 path.LinePosition = reader.LinePosition;
\r
302 path.SourceUri = reader.BaseURI;
\r
304 XmlNamespaceManager currentMgr = XmlSchemaUtil.GetParserContext (reader.Reader).NamespaceManager;
\r
305 if (currentMgr != null) {
\r
306 path.nsmgr = new XmlNamespaceManager (reader.NameTable);
\r
307 IEnumerator e = currentMgr.GetEnumerator ();
\r
308 while (e.MoveNext ()) {
\r
309 string prefix = e.Current as string;
\r
315 path.nsmgr.AddNamespace (prefix, currentMgr.LookupNamespace (prefix, false));
\r
321 while(reader.MoveToNextAttribute())
\r
323 if(reader.Name == "id")
\r
325 path.Id = reader.Value;
\r
327 else if(reader.Name == "xpath")
\r
329 path.xpath = reader.Value;
\r
331 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
\r
333 error(h,reader.Name + " is not a valid attribute for "+name,null);
\r
337 XmlSchemaUtil.ReadUnhandledAttribute(reader,path);
\r
341 reader.MoveToElement();
\r
342 if(reader.IsEmptyElement)
\r
345 // Content: (annotation?)
\r
347 while(reader.ReadNextElement())
\r
349 if(reader.NodeType == XmlNodeType.EndElement)
\r
351 if(reader.LocalName != name)
\r
352 error(h,"Should not happen :2: XmlSchemaXPath.Read, name="+reader.Name,null);
\r
355 if(level <= 1 && reader.LocalName == "annotation")
\r
357 level = 2; //Only one annotation
\r
358 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
\r
359 if(annotation != null)
\r
360 path.Annotation = annotation;
\r
363 reader.RaiseInvalidElementError();
\r