1 // Author: Dwivedi, Ajay kumar
\r
4 using System.Collections;
\r
5 using System.Xml.Serialization;
\r
6 using System.ComponentModel;
\r
9 using Mono.Xml.Schema;
\r
11 namespace System.Xml.Schema
\r
14 /// Summary description for XmlSchemaXPath.
\r
16 public class XmlSchemaXPath : XmlSchemaAnnotated
\r
18 private string xpath;
\r
19 XmlNamespaceManager nsmgr;
\r
20 internal bool isSelector;
\r
21 XsdIdentityPath [] compiledExpression;
\r
23 XsdIdentityPath currentPath;
\r
25 public XmlSchemaXPath()
\r
28 [DefaultValue(null)]
\r
29 [System.Xml.Serialization.XmlAttribute("xpath")]
\r
30 public string XPath
\r
32 get{ return xpath; }
\r
33 set{ xpath = value; }
\r
36 internal override int Compile(ValidationEventHandler h, XmlSchema schema)
\r
38 // If this is already compiled this time, simply skip.
\r
39 if (this.IsComplied (schema.CompilationId))
\r
42 if (nsmgr == null) {
\r
43 nsmgr = new XmlNamespaceManager (new NameTable ());
\r
44 if (Namespaces != null)
\r
45 foreach (XmlQualifiedName qname in Namespaces.ToArray ())
\r
46 nsmgr.AddNamespace (qname.Name, qname.Namespace);
\r
49 currentPath = new XsdIdentityPath ();
\r
50 ParseExpression (xpath, h, schema);
\r
52 XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);
\r
53 this.CompilationId = schema.CompilationId;
\r
57 internal XsdIdentityPath [] CompiledExpression {
\r
58 get { return compiledExpression; }
\r
61 private void ParseExpression (string xpath, ValidationEventHandler h, XmlSchema schema)
\r
63 ArrayList paths = new ArrayList ();
\r
64 ParsePath (xpath, 0, paths, h, schema);
\r
65 this.compiledExpression = (XsdIdentityPath []) paths.ToArray (typeof (XsdIdentityPath));
\r
68 private void ParsePath (string xpath, int pos, ArrayList paths,
\r
69 ValidationEventHandler h, XmlSchema schema)
\r
71 pos = SkipWhitespace (xpath, pos);
\r
72 if (xpath.Length >= pos + 3 && xpath [pos] == '.') {
\r
75 pos = SkipWhitespace (xpath, pos);
\r
76 if (xpath.Length > pos + 2 && xpath.IndexOf ("//", pos, 2) == pos) {
\r
77 currentPath.Descendants = true;
\r
81 pos = tmp; // revert
\r
83 ArrayList al = new ArrayList ();
\r
84 ParseStep (xpath, pos, al, paths, h, schema);
\r
87 private void ParseStep (string xpath, int pos, ArrayList steps,
\r
88 ArrayList paths, ValidationEventHandler h, XmlSchema schema)
\r
90 pos = SkipWhitespace (xpath, pos);
\r
91 if (xpath.Length == pos) {
\r
92 error (h, "Empty xpath expression is specified");
\r
96 XsdIdentityStep step = new XsdIdentityStep ();
\r
97 switch (xpath [pos]) {
\r
100 error (h, "Selector cannot include attribute axes.");
\r
101 currentPath = null;
\r
105 step.IsAttribute = true;
\r
106 pos = SkipWhitespace (xpath, pos);
\r
107 if (xpath.Length > pos && xpath [pos] == '*') {
\r
109 step.IsAnyName = true;
\r
114 pos++; // do nothing ;-)
\r
115 step.IsCurrent = true;
\r
119 step.IsAnyName = true;
\r
122 if (xpath.Length > pos + 5 && xpath.IndexOf ("child", pos, 5) == pos) {
\r
125 pos = SkipWhitespace (xpath, pos);
\r
126 if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
\r
128 if (xpath.Length > pos && xpath [pos] == '*') {
\r
130 step.IsAnyName = true;
\r
133 pos = SkipWhitespace (xpath, pos);
\r
140 if (xpath.Length > pos + 9 && xpath.IndexOf ("attribute", pos, 9) == pos) {
\r
143 pos = SkipWhitespace (xpath, pos);
\r
144 if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
\r
146 error (h, "Selector cannot include attribute axes.");
\r
147 currentPath = null;
\r
151 step.IsAttribute = true;
\r
152 if (xpath.Length > pos && xpath [pos] == '*') {
\r
154 step.IsAnyName = true;
\r
157 pos = SkipWhitespace (xpath, pos);
\r
164 int nameStart = pos;
\r
165 while (xpath.Length > pos) {
\r
166 if (!XmlChar.IsNCNameChar (xpath [pos]))
\r
171 if (pos == nameStart) {
\r
172 error (h, "Invalid path format for a field.");
\r
173 this.currentPath = null;
\r
176 if (xpath.Length == pos || xpath [pos] != ':')
\r
177 step.Name = xpath.Substring (nameStart, pos - nameStart);
\r
179 string prefix = xpath.Substring (nameStart, pos - nameStart);
\r
181 if (xpath.Length > pos && xpath [pos] == '*') {
\r
182 string ns = nsmgr.LookupNamespace (prefix);
\r
184 error (h, "Specified prefix '" + prefix + "' is not declared.");
\r
185 this.currentPath = null;
\r
191 int localNameStart = pos;
\r
192 while (xpath.Length > pos) {
\r
193 if (!XmlChar.IsNCNameChar (xpath [pos]))
\r
198 step.Name = xpath.Substring (localNameStart, pos - localNameStart);
\r
199 string ns = nsmgr.LookupNamespace (prefix);
\r
201 error (h, "Specified prefix '" + prefix + "' is not declared.");
\r
202 this.currentPath = null;
\r
205 step.Namespace = ns;
\r
210 if (!step.IsCurrent) // Current step is meaningless, other than its representation.
\r
212 pos = SkipWhitespace (xpath, pos);
\r
213 if (xpath.Length == pos) {
\r
214 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
215 paths.Add (currentPath);
\r
218 else if (xpath [pos] == '/') {
\r
220 if (step.IsAttribute) {
\r
221 error (h, "Unexpected xpath token after Attribute NameTest.");
\r
222 this.currentPath = null;
\r
225 this.ParseStep (xpath, pos, steps, paths, h, schema);
\r
226 if (currentPath == null) // For ValidationEventHandler
\r
228 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
229 } else if (xpath [pos] == '|') {
\r
231 currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
\r
232 paths.Add (this.currentPath);
\r
233 this.currentPath = new XsdIdentityPath ();
\r
234 this.ParsePath (xpath, pos, paths, h, schema);
\r
236 error (h, "Unexpected xpath token after NameTest.");
\r
237 this.currentPath = null;
\r
242 private int SkipWhitespace (string xpath, int pos)
\r
245 while (loop && xpath.Length > pos) {
\r
246 switch (xpath [pos]) {
\r
263 // xpath = a subset of XPath expression, see below
\r
264 // {any attributes with non-schema namespace . . .}>
\r
265 // Content: (annotation?)
\r
267 internal static XmlSchemaXPath Read(XmlSchemaReader reader, ValidationEventHandler h,string name)
\r
269 XmlSchemaXPath path = new XmlSchemaXPath();
\r
270 reader.MoveToElement();
\r
272 if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != name)
\r
274 error(h,"Should not happen :1: XmlSchemaComplexContentRestriction.Read, name="+reader.Name,null);
\r
279 path.LineNumber = reader.LineNumber;
\r
280 path.LinePosition = reader.LinePosition;
\r
281 path.SourceUri = reader.BaseURI;
\r
283 XmlNamespaceManager currentMgr = XmlSchemaUtil.GetParserContext (reader.Reader).NamespaceManager;
\r
284 if (currentMgr != null) {
\r
285 path.nsmgr = new XmlNamespaceManager (reader.NameTable);
\r
286 IEnumerator e = currentMgr.GetEnumerator ();
\r
287 while (e.MoveNext ()) {
\r
288 string prefix = e.Current as string;
\r
294 path.nsmgr.AddNamespace (prefix, currentMgr.LookupNamespace (prefix));
\r
300 while(reader.MoveToNextAttribute())
\r
302 if(reader.Name == "id")
\r
304 path.Id = reader.Value;
\r
306 else if(reader.Name == "xpath")
\r
308 path.xpath = reader.Value;
\r
310 else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
\r
312 error(h,reader.Name + " is not a valid attribute for "+name,null);
\r
316 XmlSchemaUtil.ReadUnhandledAttribute(reader,path);
\r
320 reader.MoveToElement();
\r
321 if(reader.IsEmptyElement)
\r
324 // Content: (annotation?)
\r
326 while(reader.ReadNextElement())
\r
328 if(reader.NodeType == XmlNodeType.EndElement)
\r
330 if(reader.LocalName != name)
\r
331 error(h,"Should not happen :2: XmlSchemaXPath.Read, name="+reader.Name,null);
\r
334 if(level <= 1 && reader.LocalName == "annotation")
\r
336 level = 2; //Only one annotation
\r
337 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
\r
338 if(annotation != null)
\r
339 path.Annotation = annotation;
\r
342 reader.RaiseInvalidElementError();
\r