| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- // Author: Dwivedi, Ajay kumar
- // [email protected]
- using System;
- using System.Collections;
- using System.Xml.Serialization;
- using System.ComponentModel;
- using System.Xml;
- using Mono.Xml;
- using Mono.Xml.Schema;
- namespace System.Xml.Schema
- {
- /// <summary>
- /// Summary description for XmlSchemaXPath.
- /// </summary>
- public class XmlSchemaXPath : XmlSchemaAnnotated
- {
- private string xpath;
- XmlNamespaceManager nsmgr;
- internal bool isSelector;
- XsdIdentityPath [] compiledExpression;
- XsdIdentityPath currentPath;
- public XmlSchemaXPath()
- {
- }
- [DefaultValue(null)]
- [System.Xml.Serialization.XmlAttribute("xpath")]
- public string XPath
- {
- get{ return xpath; }
- set{ xpath = value; }
- }
- internal override int Compile(ValidationEventHandler h, XmlSchema schema)
- {
- // If this is already compiled this time, simply skip.
- if (this.IsComplied (schema.CompilationId))
- return 0;
- if (nsmgr == null) {
- nsmgr = new XmlNamespaceManager (new NameTable ());
- if (Namespaces != null)
- foreach (XmlQualifiedName qname in Namespaces.ToArray ())
- nsmgr.AddNamespace (qname.Name, qname.Namespace);
- }
- currentPath = new XsdIdentityPath ();
- ParseExpression (xpath, h, schema);
- XmlSchemaUtil.CompileID(Id, this, schema.IDCollection, h);
- this.CompilationId = schema.CompilationId;
- return errorCount;
- }
- internal XsdIdentityPath [] CompiledExpression {
- get { return compiledExpression; }
- }
- private void ParseExpression (string xpath, ValidationEventHandler h, XmlSchema schema)
- {
- ArrayList paths = new ArrayList ();
- ParsePath (xpath, 0, paths, h, schema);
- this.compiledExpression = (XsdIdentityPath []) paths.ToArray (typeof (XsdIdentityPath));
- }
- private void ParsePath (string xpath, int pos, ArrayList paths,
- ValidationEventHandler h, XmlSchema schema)
- {
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length >= pos + 3 && xpath [pos] == '.') {
- int tmp = pos;
- pos++;
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length > pos + 2 && xpath.IndexOf ("//", pos, 2) == pos) {
- currentPath.Descendants = true;
- pos += 2;
- }
- else
- pos = tmp; // revert
- }
- ArrayList al = new ArrayList ();
- ParseStep (xpath, pos, al, paths, h, schema);
- }
- private void ParseStep (string xpath, int pos, ArrayList steps,
- ArrayList paths, ValidationEventHandler h, XmlSchema schema)
- {
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length == pos) {
- error (h, "Empty xpath expression is specified");
- return;
- }
- XsdIdentityStep step = new XsdIdentityStep ();
- switch (xpath [pos]) {
- case '@':
- if (isSelector) {
- error (h, "Selector cannot include attribute axes.");
- currentPath = null;
- return;
- }
- pos++;
- step.IsAttribute = true;
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length > pos && xpath [pos] == '*') {
- pos++;
- step.IsAnyName = true;
- break;
- }
- goto default;
- case '.':
- pos++; // do nothing ;-)
- step.IsCurrent = true;
- break;
- case '*':
- pos++;
- step.IsAnyName = true;
- break;
- case 'c':
- if (xpath.Length > pos + 5 && xpath.IndexOf ("child", pos, 5) == pos) {
- int tmp = pos;
- pos += 5;
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
- pos += 2;
- if (xpath.Length > pos && xpath [pos] == '*') {
- pos++;
- step.IsAnyName = true;
- break;
- }
- pos = SkipWhitespace (xpath, pos);
- }
- else
- pos = tmp;
- }
- goto default;
- case 'a':
- if (xpath.Length > pos + 9 && xpath.IndexOf ("attribute", pos, 9) == pos) {
- int tmp = pos;
- pos += 9;
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length > pos && xpath [pos] == ':' && xpath [pos+1] == ':') {
- if (isSelector) {
- error (h, "Selector cannot include attribute axes.");
- currentPath = null;
- return;
- }
- pos += 2;
- step.IsAttribute = true;
- if (xpath.Length > pos && xpath [pos] == '*') {
- pos++;
- step.IsAnyName = true;
- break;
- }
- pos = SkipWhitespace (xpath, pos);
- }
- else
- pos = tmp;
- }
- goto default;
- default:
- int nameStart = pos;
- while (xpath.Length > pos) {
- if (!XmlChar.IsNCNameChar (xpath [pos]))
- break;
- else
- pos++;
- }
- if (pos == nameStart) {
- error (h, "Invalid path format for a field.");
- this.currentPath = null;
- return;
- }
- if (xpath.Length == pos || xpath [pos] != ':')
- step.Name = xpath.Substring (nameStart, pos - nameStart);
- else {
- string prefix = xpath.Substring (nameStart, pos - nameStart);
- pos++;
- if (xpath.Length > pos && xpath [pos] == '*') {
- string ns = nsmgr.LookupNamespace (prefix);
- if (ns == null) {
- error (h, "Specified prefix '" + prefix + "' is not declared.");
- this.currentPath = null;
- return;
- }
- step.NsName = ns;
- pos++;
- } else {
- int localNameStart = pos;
- while (xpath.Length > pos) {
- if (!XmlChar.IsNCNameChar (xpath [pos]))
- break;
- else
- pos++;
- }
- step.Name = xpath.Substring (localNameStart, pos - localNameStart);
- string ns = nsmgr.LookupNamespace (prefix);
- if (ns == null) {
- error (h, "Specified prefix '" + prefix + "' is not declared.");
- this.currentPath = null;
- return;
- }
- step.Namespace = ns;
- }
- }
- break;
- }
- if (!step.IsCurrent) // Current step is meaningless, other than its representation.
- steps.Add (step);
- pos = SkipWhitespace (xpath, pos);
- if (xpath.Length == pos) {
- currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
- paths.Add (currentPath);
- return;
- }
- else if (xpath [pos] == '/') {
- pos++;
- if (step.IsAttribute) {
- error (h, "Unexpected xpath token after Attribute NameTest.");
- this.currentPath = null;
- return;
- }
- this.ParseStep (xpath, pos, steps, paths, h, schema);
- if (currentPath == null) // For ValidationEventHandler
- return;
- currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
- } else if (xpath [pos] == '|') {
- pos++;
- currentPath.OrderedSteps = (XsdIdentityStep []) steps.ToArray (typeof (XsdIdentityStep));
- paths.Add (this.currentPath);
- this.currentPath = new XsdIdentityPath ();
- this.ParsePath (xpath, pos, paths, h, schema);
- } else {
- error (h, "Unexpected xpath token after NameTest.");
- this.currentPath = null;
- return;
- }
- }
- private int SkipWhitespace (string xpath, int pos)
- {
- bool loop = true;
- while (loop && xpath.Length > pos) {
- switch (xpath [pos]) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- pos++;
- continue;
- default:
- loop = false;
- break;
- }
- }
- return pos;
- }
- //<selector
- // id = ID
- // xpath = a subset of XPath expression, see below
- // {any attributes with non-schema namespace . . .}>
- // Content: (annotation?)
- //</selector>
- internal static XmlSchemaXPath Read(XmlSchemaReader reader, ValidationEventHandler h,string name)
- {
- XmlSchemaXPath path = new XmlSchemaXPath();
- reader.MoveToElement();
- if(reader.NamespaceURI != XmlSchema.Namespace || reader.LocalName != name)
- {
- error(h,"Should not happen :1: XmlSchemaComplexContentRestriction.Read, name="+reader.Name,null);
- reader.Skip();
- return null;
- }
- path.LineNumber = reader.LineNumber;
- path.LinePosition = reader.LinePosition;
- path.SourceUri = reader.BaseURI;
- XmlNamespaceManager currentMgr = XmlSchemaUtil.GetParserContext (reader.Reader).NamespaceManager;
- if (currentMgr != null) {
- path.nsmgr = new XmlNamespaceManager (reader.NameTable);
- IEnumerator e = currentMgr.GetEnumerator ();
- while (e.MoveNext ()) {
- string prefix = e.Current as string;
- switch (prefix) {
- case "xml":
- case "xmlns":
- continue;
- default:
- path.nsmgr.AddNamespace (prefix, currentMgr.LookupNamespace (prefix));
- break;
- }
- }
- }
- while(reader.MoveToNextAttribute())
- {
- if(reader.Name == "id")
- {
- path.Id = reader.Value;
- }
- else if(reader.Name == "xpath")
- {
- path.xpath = reader.Value;
- }
- else if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
- {
- error(h,reader.Name + " is not a valid attribute for "+name,null);
- }
- else
- {
- XmlSchemaUtil.ReadUnhandledAttribute(reader,path);
- }
- }
- reader.MoveToElement();
- if(reader.IsEmptyElement)
- return path;
- // Content: (annotation?)
- int level = 1;
- while(reader.ReadNextElement())
- {
- if(reader.NodeType == XmlNodeType.EndElement)
- {
- if(reader.LocalName != name)
- error(h,"Should not happen :2: XmlSchemaXPath.Read, name="+reader.Name,null);
- break;
- }
- if(level <= 1 && reader.LocalName == "annotation")
- {
- level = 2; //Only one annotation
- XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
- if(annotation != null)
- path.Annotation = annotation;
- continue;
- }
- reader.RaiseInvalidElementError();
- }
- return path;
- }
- }
- }
|