public XsdIdentityPath SelectorMatches(ArrayList qnameStack, int depth) { for (int i = 0; i < this.Selector.Paths.Length; i++) { XsdIdentityPath xsdIdentityPath = this.Selector.Paths[i]; if (depth == this.StartDepth) { if (xsdIdentityPath.OrderedSteps.Length == 0) { return(xsdIdentityPath); } } else if (depth - this.StartDepth >= xsdIdentityPath.OrderedSteps.Length - 1) { int num = xsdIdentityPath.OrderedSteps.Length; if (xsdIdentityPath.OrderedSteps[num - 1].IsAttribute) { num--; } if (!xsdIdentityPath.Descendants || depth >= this.StartDepth + num) { if (xsdIdentityPath.Descendants || depth == this.StartDepth + num) { num--; int num2 = 0; while (0 <= num) { XsdIdentityStep xsdIdentityStep = xsdIdentityPath.OrderedSteps[num]; if (!xsdIdentityStep.IsAnyName) { XmlQualifiedName xmlQualifiedName = (XmlQualifiedName)qnameStack[qnameStack.Count - num2 - 1]; if (xsdIdentityStep.NsName == null || !(xmlQualifiedName.Namespace == xsdIdentityStep.NsName)) { if (!(xsdIdentityStep.Name == xmlQualifiedName.Name) || !(xsdIdentityStep.Namespace == xmlQualifiedName.Namespace)) { if (this.alwaysTrue) { break; } } } } num2++; num--; } if (num < 0) { return(xsdIdentityPath); } } } } } return(null); }
// In this method, attributes are ignored. // It might throw Exception. public void ProcessMatch(bool isAttribute, ArrayList qnameStack, object sender, XmlNameTable nameTable, string sourceUri, object schemaType, NSResolver nsResolver, IXmlLineInfo li, int depth, string attrName, string attrNS, object attrValue, bool isXsiNil, ArrayList currentKeyFieldConsumers) { for (int i = 0; i < KeyFields.Count; i++) { XsdKeyEntryField keyField = KeyFields [i]; XsdIdentityPath path = keyField.Matches(isAttribute, sender, nameTable, qnameStack, sourceUri, schemaType, nsResolver, li, depth, attrName, attrNS, attrValue); if (path == null) { continue; } if (keyField.FieldFound) { // HACK: This is not logical by nature. Attributes never be cosuming, // so I used it as a temporary mark to sign it is *just* validated now. if (!keyField.Consuming) { throw new ValException("Two or more matching field was found.", sender, sourceUri, this.OwnerSequence.SourceSchemaIdentity, null); } else { keyField.Consuming = false; } } if (keyField.Consumed) { continue; } if (isXsiNil && !keyField.SetIdentityField(Guid.Empty, true, XsdAnySimpleType.Instance, depth, li)) { throw new ValException("Two or more identical field was found.", sender, sourceUri, OwnerSequence.SourceSchemaIdentity, null); } XmlSchemaComplexType ct = schemaType as XmlSchemaComplexType; if (ct != null && (ct.ContentType == XmlSchemaContentType.Empty || ct.ContentType == XmlSchemaContentType.ElementOnly) && schemaType != XmlSchemaComplexType.AnyType) { throw new ValException("Specified schema type is complex type, which is not allowed for identity constraints.", sender, sourceUri, OwnerSequence.SourceSchemaIdentity, null); } keyField.FieldFound = true; keyField.FieldFoundPath = path; keyField.FieldFoundDepth = depth; keyField.Consuming = true; if (li != null && li.HasLineInfo()) { keyField.FieldHasLineInfo = true; keyField.FieldLineNumber = li.LineNumber; keyField.FieldLinePosition = li.LinePosition; } currentKeyFieldConsumers.Add(keyField); } }
public void ProcessMatch(bool isAttribute, ArrayList qnameStack, object sender, XmlNameTable nameTable, string sourceUri, object schemaType, IXmlNamespaceResolver nsResolver, IXmlLineInfo li, int depth, string attrName, string attrNS, object attrValue, bool isXsiNil, ArrayList currentKeyFieldConsumers) { for (int i = 0; i < this.KeyFields.Count; i++) { XsdKeyEntryField xsdKeyEntryField = this.KeyFields[i]; XsdIdentityPath xsdIdentityPath = xsdKeyEntryField.Matches(isAttribute, sender, nameTable, qnameStack, sourceUri, schemaType, nsResolver, li, depth, attrName, attrNS, attrValue); if (xsdIdentityPath != null) { if (xsdKeyEntryField.FieldFound) { if (!xsdKeyEntryField.Consuming) { throw new XmlSchemaValidationException("Two or more matching field was found.", sender, sourceUri, this.OwnerSequence.SourceSchemaIdentity, null); } xsdKeyEntryField.Consuming = false; } if (!xsdKeyEntryField.Consumed) { if (isXsiNil && !xsdKeyEntryField.SetIdentityField(Guid.Empty, true, XsdAnySimpleType.Instance, depth, li)) { throw new XmlSchemaValidationException("Two or more identical field was found.", sender, sourceUri, this.OwnerSequence.SourceSchemaIdentity, null); } XmlSchemaComplexType xmlSchemaComplexType = schemaType as XmlSchemaComplexType; if (xmlSchemaComplexType != null && (xmlSchemaComplexType.ContentType == XmlSchemaContentType.Empty || xmlSchemaComplexType.ContentType == XmlSchemaContentType.ElementOnly) && schemaType != XmlSchemaComplexType.AnyType) { throw new XmlSchemaValidationException("Specified schema type is complex type, which is not allowed for identity constraints.", sender, sourceUri, this.OwnerSequence.SourceSchemaIdentity, null); } xsdKeyEntryField.FieldFound = true; xsdKeyEntryField.FieldFoundPath = xsdIdentityPath; xsdKeyEntryField.FieldFoundDepth = depth; xsdKeyEntryField.Consuming = true; if (li != null && li.HasLineInfo()) { xsdKeyEntryField.FieldHasLineInfo = true; xsdKeyEntryField.FieldLineNumber = li.LineNumber; xsdKeyEntryField.FieldLinePosition = li.LinePosition; } currentKeyFieldConsumers.Add(xsdKeyEntryField); } } } }
internal override int Compile(ValidationEventHandler h, XmlSchema schema) { // If this is already compiled this time, simply skip. if (CompilationId == 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; }
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, false); 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, false); 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; } }
// if matchesAttr then check attributes; otherwise check elements. internal XsdIdentityPath Matches(bool matchesAttr, object sender, XmlNameTable nameTable, ArrayList qnameStack, string sourceUri, object schemaType, NSResolver nsResolver, IXmlLineInfo lineInfo, int depth, string attrName, string attrNS, object attrValue) { XsdIdentityPath matchedAttrPath = null; for (int i = 0; i < field.Paths.Length; i++) { XsdIdentityPath path = field.Paths [i]; bool isAttribute = path.IsAttribute; if (matchesAttr != isAttribute) { continue; } XsdIdentityStep step; if (path.IsAttribute) { step = path.OrderedSteps [path.OrderedSteps.Length - 1]; bool match = false; if (step.IsAnyName || step.NsName != null) { if (step.IsAnyName || attrNS == step.NsName) { match = true; } } else if (step.Name == attrName && step.Namespace == attrNS) { match = true; } if (!match) { continue; } // first -1 is to reduce attr path step, next -1 is to reduce Attribute's depth in XmlReader. if (entry.StartDepth + (path.OrderedSteps.Length - 1) != depth - 1) { continue; // matched at different nest level } matchedAttrPath = path; } if (FieldFound && (depth > this.FieldFoundDepth && this.FieldFoundPath == path)) { continue; // don't return; other fields might hit errorneously. } // Only "." hits. if (path.OrderedSteps.Length == 0) { if (depth == entry.StartDepth) { return(path); } else { continue; } } // It does not hit as yet (too shallow to hit). if (depth - entry.StartDepth < path.OrderedSteps.Length - 1) { continue; } int iter = path.OrderedSteps.Length; if (isAttribute) { iter--; } if (path.Descendants && depth < entry.StartDepth + iter) { continue; } else if (!path.Descendants && depth != entry.StartDepth + iter) { continue; } iter--; for (; iter >= 0; iter--) { step = path.OrderedSteps [iter]; if (step.IsCurrent || step.IsAnyName) { continue; } XmlQualifiedName qname = (XmlQualifiedName)qnameStack [entry.StartDepth + iter + (isAttribute ? 0 : 1)]; if (step.NsName != null && qname.Namespace == step.NsName) { continue; } if ((step.Name == "*" || step.Name == qname.Name) && step.Namespace == qname.Namespace) { continue; } else { break; } } if (iter >= 0) // i.e. did not match against the path. { continue; } if (!matchesAttr) { return(path); } } if (matchedAttrPath != null) { this.FillAttributeFieldValue(sender, nameTable, sourceUri, schemaType, nsResolver, attrValue, lineInfo, depth); if (this.Identity != null) { return(matchedAttrPath); } } return(null); }
// In this method, attributes are ignored. public XsdIdentityPath SelectorMatches(ArrayList qnameStack, int depth) { for (int i = 0; i < Selector.Paths.Length; i++) { XsdIdentityPath path = Selector.Paths [i]; // Only "." hits. if (depth == this.StartDepth) { if (path.OrderedSteps.Length == 0) { return(path); } else { continue; } } // It does not hit as yet (too shallow to hit). if (depth - this.StartDepth < path.OrderedSteps.Length - 1) { continue; } int iter = path.OrderedSteps.Length; if (path.OrderedSteps [iter - 1].IsAttribute) { iter--; } if (path.Descendants && depth < this.StartDepth + iter) { continue; } else if (!path.Descendants && depth != this.StartDepth + iter) { continue; } iter--; XsdIdentityStep step; for (int x = 0; 0 <= iter; x++, iter--) { step = path.OrderedSteps [iter]; if (step.IsAnyName) { continue; } XmlQualifiedName qname = (XmlQualifiedName)qnameStack [qnameStack.Count - x - 1]; if (step.NsName != null && qname.Namespace == step.NsName) { continue; } if (step.Name == qname.Name && step.Namespace == qname.Namespace) { continue; } if (alwaysTrue) { break; } } if (iter >= 0) // i.e. did not match against the path. { continue; } return(path); } return(null); }
internal XsdIdentityPath Matches(bool matchesAttr, object sender, XmlNameTable nameTable, ArrayList qnameStack, string sourceUri, object schemaType, IXmlNamespaceResolver nsResolver, IXmlLineInfo lineInfo, int depth, string attrName, string attrNS, object attrValue) { XsdIdentityPath xsdIdentityPath = null; for (int i = 0; i < this.field.Paths.Length; i++) { XsdIdentityPath xsdIdentityPath2 = this.field.Paths[i]; bool isAttribute = xsdIdentityPath2.IsAttribute; if (matchesAttr == isAttribute) { if (xsdIdentityPath2.IsAttribute) { XsdIdentityStep xsdIdentityStep = xsdIdentityPath2.OrderedSteps[xsdIdentityPath2.OrderedSteps.Length - 1]; bool flag = false; if (xsdIdentityStep.IsAnyName || xsdIdentityStep.NsName != null) { if (xsdIdentityStep.IsAnyName || attrNS == xsdIdentityStep.NsName) { flag = true; } } else if (xsdIdentityStep.Name == attrName && xsdIdentityStep.Namespace == attrNS) { flag = true; } if (!flag) { goto IL_2AF; } if (this.entry.StartDepth + (xsdIdentityPath2.OrderedSteps.Length - 1) != depth - 1) { goto IL_2AF; } xsdIdentityPath = xsdIdentityPath2; } if (!this.FieldFound || depth <= this.FieldFoundDepth || this.FieldFoundPath != xsdIdentityPath2) { if (xsdIdentityPath2.OrderedSteps.Length == 0) { if (depth == this.entry.StartDepth) { return(xsdIdentityPath2); } } else if (depth - this.entry.StartDepth >= xsdIdentityPath2.OrderedSteps.Length - 1) { int j = xsdIdentityPath2.OrderedSteps.Length; if (isAttribute) { j--; } if (!xsdIdentityPath2.Descendants || depth >= this.entry.StartDepth + j) { if (xsdIdentityPath2.Descendants || depth == this.entry.StartDepth + j) { for (j--; j >= 0; j--) { XsdIdentityStep xsdIdentityStep = xsdIdentityPath2.OrderedSteps[j]; if (!xsdIdentityStep.IsCurrent && !xsdIdentityStep.IsAnyName) { XmlQualifiedName xmlQualifiedName = (XmlQualifiedName)qnameStack[this.entry.StartDepth + j + ((!isAttribute) ? 1 : 0)]; if (xsdIdentityStep.NsName == null || !(xmlQualifiedName.Namespace == xsdIdentityStep.NsName)) { if ((!(xsdIdentityStep.Name == "*") && !(xsdIdentityStep.Name == xmlQualifiedName.Name)) || !(xsdIdentityStep.Namespace == xmlQualifiedName.Namespace)) { break; } } } } if (j < 0) { if (!matchesAttr) { return(xsdIdentityPath2); } } } } } } } IL_2AF :; } if (xsdIdentityPath != null) { this.FillAttributeFieldValue(sender, nameTable, sourceUri, schemaType, nsResolver, attrValue, lineInfo, depth); if (this.Identity != null) { return(xsdIdentityPath); } } return(null); }