2 //------------------------------------------------------------------------------
3 // <copyright file="XsdValidatingReader.cs" company="Microsoft">
4 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <owner current="true" primary="true">[....]</owner>
7 //------------------------------------------------------------------------------
11 using System.Xml.Schema;
12 using System.Xml.XPath;
13 using System.Diagnostics;
14 using System.Globalization;
15 using System.Collections;
16 using System.Security.Policy;
17 using System.Collections.Generic;
18 using System.Runtime.Versioning;
20 namespace System.Xml {
22 internal delegate void CachingEventHandler(XsdCachingReader cachingReader);
24 internal class AttributePSVIInfo {
25 internal string localName;
26 internal string namespaceUri;
27 internal object typedAttributeValue;
28 internal XmlSchemaInfo attributeSchemaInfo;
30 internal AttributePSVIInfo() {
31 attributeSchemaInfo = new XmlSchemaInfo();
34 internal void Reset() {
35 typedAttributeValue = null;
36 localName = string.Empty;
37 namespaceUri = string.Empty;
38 attributeSchemaInfo.Clear();
42 internal partial class XsdValidatingReader : XmlReader, IXmlSchemaInfo, IXmlLineInfo, IXmlNamespaceResolver {
44 private enum ValidatingReaderState {
48 OnDefaultAttribute = -1,
49 OnReadAttributeValue = -2,
52 ParseInlineSchema = 5,
54 OnReadBinaryContent = 7,
60 private XmlReader coreReader;
61 private IXmlNamespaceResolver coreReaderNSResolver;
62 private IXmlNamespaceResolver thisNSResolver;
63 private XmlSchemaValidator validator;
64 private XmlResolver xmlResolver;
65 private ValidationEventHandler validationEvent;
66 private ValidatingReaderState validationState;
67 private XmlValueGetter valueGetter;
69 // namespace management
70 XmlNamespaceManager nsManager;
71 bool manageNamespaces;
72 bool processInlineSchema;
75 //Current Node handling
76 private ValidatingReaderNodeData cachedNode; //Used to cache current node when looking ahead or default attributes
77 private AttributePSVIInfo attributePSVI;
80 int attributeCount; //Total count of attributes including default
81 int coreReaderAttributeCount;
83 AttributePSVIInfo[] attributePSVINodes;
84 ArrayList defaultAttributes;
87 private Parser inlineSchemaParser = null;
90 private object atomicValue;
91 private XmlSchemaInfo xmlSchemaInfo;
93 // original string of the atomic value
94 private string originalAtomicValueString;
96 //cached coreReader information
97 private XmlNameTable coreReaderNameTable;
98 private XsdCachingReader cachingReader;
100 //ReadAttributeValue TextNode
101 private ValidatingReaderNodeData textNode;
103 //To avoid SchemaNames creation
104 private string NsXmlNs;
106 private string NsXsi;
107 private string XsiType;
108 private string XsiNil;
109 private string XsdSchema;
110 private string XsiSchemaLocation;
111 private string XsiNoNamespaceSchemaLocation;
113 //XmlCharType instance
114 private XmlCharType xmlCharType = XmlCharType.Instance;
116 //Underlying reader's IXmlLineInfo
117 IXmlLineInfo lineInfo;
119 // helpers for Read[Element]ContentAs{Base64,BinHex} methods
120 ReadContentAsBinaryHelper readBinaryHelper;
121 ValidatingReaderState savedState;
124 private const int InitialAttributeCount = 8;
126 static volatile Type TypeOfString;
129 internal XsdValidatingReader(XmlReader reader, XmlResolver xmlResolver, XmlReaderSettings readerSettings, XmlSchemaObject partialValidationType) {
130 this.coreReader = reader;
131 this.coreReaderNSResolver = reader as IXmlNamespaceResolver;
132 this.lineInfo = reader as IXmlLineInfo;
133 coreReaderNameTable = coreReader.NameTable;
134 if (coreReaderNSResolver == null) {
135 nsManager = new XmlNamespaceManager(coreReaderNameTable);
136 manageNamespaces = true;
138 thisNSResolver = this as IXmlNamespaceResolver;
139 this.xmlResolver = xmlResolver;
140 this.processInlineSchema = (readerSettings.ValidationFlags & XmlSchemaValidationFlags.ProcessInlineSchema) != 0;
142 SetupValidator(readerSettings, reader, partialValidationType);
143 validationEvent = readerSettings.GetEventHandler();
146 internal XsdValidatingReader(XmlReader reader, XmlResolver xmlResolver, XmlReaderSettings readerSettings)
148 this(reader, xmlResolver, readerSettings, null) { }
150 private void Init() {
151 validationState = ValidatingReaderState.Init;
152 defaultAttributes = new ArrayList();
153 currentAttrIndex = -1;
154 attributePSVINodes = new AttributePSVIInfo[InitialAttributeCount];
155 valueGetter = new XmlValueGetter(GetStringValue);
156 TypeOfString = typeof(System.String);
157 xmlSchemaInfo = new XmlSchemaInfo();
159 //Add common strings to be compared to NameTable
160 NsXmlNs = coreReaderNameTable.Add(XmlReservedNs.NsXmlNs);
161 NsXs = coreReaderNameTable.Add(XmlReservedNs.NsXs);
162 NsXsi = coreReaderNameTable.Add(XmlReservedNs.NsXsi);
163 XsiType = coreReaderNameTable.Add("type");
164 XsiNil = coreReaderNameTable.Add("nil");
165 XsiSchemaLocation = coreReaderNameTable.Add("schemaLocation");
166 XsiNoNamespaceSchemaLocation = coreReaderNameTable.Add("noNamespaceSchemaLocation");
167 XsdSchema = coreReaderNameTable.Add("schema");
170 private void SetupValidator(XmlReaderSettings readerSettings, XmlReader reader, XmlSchemaObject partialValidationType) {
171 validator = new XmlSchemaValidator(coreReaderNameTable, readerSettings.Schemas, thisNSResolver, readerSettings.ValidationFlags);
172 validator.XmlResolver = this.xmlResolver;
173 validator.SourceUri = XmlConvert.ToUri(reader.BaseURI); //Not using XmlResolver.ResolveUri as it checks for relative Uris,reader.BaseURI will be absolute file paths or string.Empty
174 validator.ValidationEventSender = this;
175 validator.ValidationEventHandler += readerSettings.GetEventHandler();
176 validator.LineInfoProvider = this.lineInfo;
177 if (validator.ProcessSchemaHints) {
178 validator.SchemaSet.ReaderSettings.DtdProcessing = readerSettings.DtdProcessing;
180 validator.SetDtdSchemaInfo(reader.DtdInfo);
181 if (partialValidationType != null) {
182 validator.Initialize(partialValidationType);
185 validator.Initialize();
190 public override XmlReaderSettings Settings {
192 XmlReaderSettings settings = coreReader.Settings;
193 if (null != settings)
194 settings = settings.Clone();
195 if (settings == null) {
196 settings = new XmlReaderSettings();
198 settings.Schemas = validator.SchemaSet;
199 settings.ValidationType = ValidationType.Schema;
200 settings.ValidationFlags = validator.ValidationFlags;
201 settings.ReadOnly = true;
208 // Gets the type of the current node.
209 public override XmlNodeType NodeType {
211 if ((int)validationState < 0) {
212 return cachedNode.NodeType;
215 XmlNodeType nodeType = coreReader.NodeType;
216 //Check for significant whitespace
217 if (nodeType == XmlNodeType.Whitespace && (validator.CurrentContentType == XmlSchemaContentType.TextOnly || validator.CurrentContentType == XmlSchemaContentType.Mixed)) {
218 return XmlNodeType.SignificantWhitespace;
225 // Gets the name of the current node, including the namespace prefix.
226 public override string Name {
228 if (validationState == ValidatingReaderState.OnDefaultAttribute) {
229 string prefix = validator.GetDefaultAttributePrefix(cachedNode.Namespace);
230 if (prefix != null && prefix.Length != 0) {
231 return string.Concat(prefix + ":" + cachedNode.LocalName);
233 return cachedNode.LocalName;
235 return coreReader.Name;
239 // Gets the name of the current node without the namespace prefix.
240 public override string LocalName {
242 if ((int)validationState < 0) {
243 return cachedNode.LocalName;
245 return coreReader.LocalName;
249 // Gets the namespace URN (as defined in the W3C Namespace Specification) of the current namespace scope.
250 public override string NamespaceURI {
252 if ((int)validationState < 0) {
253 return cachedNode.Namespace;
255 return coreReader.NamespaceURI;
259 // Gets the namespace prefix associated with the current node.
260 public override string Prefix {
262 if ((int)validationState < 0) {
263 return cachedNode.Prefix;
265 return coreReader.Prefix;
269 // Gets a value indicating whether the current node can have a non-empty Value
270 public override bool HasValue {
272 if ((int)validationState < 0) {
275 return coreReader.HasValue;
279 // Gets the text value of the current node.
280 public override string Value {
282 if ((int)validationState < 0) {
283 return cachedNode.RawValue;
285 return coreReader.Value;
289 // Gets the depth of the current node in the XML element stack.
290 public override int Depth {
292 if ((int)validationState < 0) {
293 return cachedNode.Depth;
295 return coreReader.Depth;
299 // Gets the base URI of the current node.
300 public override string BaseURI {
302 return coreReader.BaseURI;
306 // Gets a value indicating whether the current node is an empty element (for example, <MyElement/>).
307 public override bool IsEmptyElement {
309 return coreReader.IsEmptyElement;
313 // Gets a value indicating whether the current node is an attribute that was generated from the default value defined
314 // in the DTD or schema.
315 public override bool IsDefault {
317 if (validationState == ValidatingReaderState.OnDefaultAttribute) { //XSD default attributes
320 return coreReader.IsDefault; //This is DTD Default attribute
324 // Gets the quotation mark character used to enclose the value of an attribute node.
325 public override char QuoteChar {
327 return coreReader.QuoteChar;
331 // Gets the current xml:space scope.
332 public override XmlSpace XmlSpace {
334 return coreReader.XmlSpace;
338 // Gets the current xml:lang scope.
339 public override string XmlLang {
341 return coreReader.XmlLang;
345 public override IXmlSchemaInfo SchemaInfo {
347 return this as IXmlSchemaInfo;
351 public override System.Type ValueType {
354 case XmlNodeType.Element:
355 case XmlNodeType.EndElement: //
356 if (xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) {
357 return xmlSchemaInfo.SchemaType.Datatype.ValueType;
361 case XmlNodeType.Attribute:
362 if (attributePSVI != null && AttributeSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) {
363 return AttributeSchemaInfo.SchemaType.Datatype.ValueType;
373 public override object ReadContentAsObject() {
374 if (!CanReadContentAs(this.NodeType)) {
375 throw CreateReadContentAsException("ReadContentAsObject");
378 return InternalReadContentAsObject(true);
382 public override bool ReadContentAsBoolean() {
383 if (!CanReadContentAs(this.NodeType)) {
384 throw CreateReadContentAsException("ReadContentAsBoolean");
386 object typedValue = InternalReadContentAsObject();
387 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
389 if (xmlType != null) {
390 return xmlType.ValueConverter.ToBoolean(typedValue);
393 return XmlUntypedConverter.Untyped.ToBoolean(typedValue);
396 catch (InvalidCastException e) {
397 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
399 catch (FormatException e) {
400 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
402 catch (OverflowException e) {
403 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
407 public override DateTime ReadContentAsDateTime() {
408 if (!CanReadContentAs(this.NodeType)) {
409 throw CreateReadContentAsException("ReadContentAsDateTime");
411 object typedValue = InternalReadContentAsObject();
412 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
414 if (xmlType != null) {
415 return xmlType.ValueConverter.ToDateTime(typedValue);
418 return XmlUntypedConverter.Untyped.ToDateTime(typedValue);
421 catch (InvalidCastException e) {
422 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
424 catch (FormatException e) {
425 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
427 catch (OverflowException e) {
428 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
432 public override double ReadContentAsDouble() {
433 if (!CanReadContentAs(this.NodeType)) {
434 throw CreateReadContentAsException("ReadContentAsDouble");
436 object typedValue = InternalReadContentAsObject();
437 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
439 if (xmlType != null) {
440 return xmlType.ValueConverter.ToDouble(typedValue);
443 return XmlUntypedConverter.Untyped.ToDouble(typedValue);
446 catch (InvalidCastException e) {
447 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
449 catch (FormatException e) {
450 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
452 catch (OverflowException e) {
453 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
457 public override float ReadContentAsFloat() {
458 if (!CanReadContentAs(this.NodeType)) {
459 throw CreateReadContentAsException("ReadContentAsFloat");
461 object typedValue = InternalReadContentAsObject();
462 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
464 if (xmlType != null) {
465 return xmlType.ValueConverter.ToSingle(typedValue);
468 return XmlUntypedConverter.Untyped.ToSingle(typedValue);
471 catch (InvalidCastException e) {
472 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
474 catch (FormatException e) {
475 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
477 catch (OverflowException e) {
478 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
482 public override decimal ReadContentAsDecimal() {
483 if (!CanReadContentAs(this.NodeType)) {
484 throw CreateReadContentAsException("ReadContentAsDecimal");
486 object typedValue = InternalReadContentAsObject();
487 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
489 if (xmlType != null) {
490 return xmlType.ValueConverter.ToDecimal(typedValue);
493 return XmlUntypedConverter.Untyped.ToDecimal(typedValue);
496 catch (InvalidCastException e) {
497 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
499 catch (FormatException e) {
500 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
502 catch (OverflowException e) {
503 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
507 public override int ReadContentAsInt() {
508 if (!CanReadContentAs(this.NodeType)) {
509 throw CreateReadContentAsException("ReadContentAsInt");
511 object typedValue = InternalReadContentAsObject();
512 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
514 if (xmlType != null) {
515 return xmlType.ValueConverter.ToInt32(typedValue);
518 return XmlUntypedConverter.Untyped.ToInt32(typedValue);
521 catch (InvalidCastException e) {
522 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
524 catch (FormatException e) {
525 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
527 catch (OverflowException e) {
528 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
532 public override long ReadContentAsLong() {
533 if (!CanReadContentAs(this.NodeType)) {
534 throw CreateReadContentAsException("ReadContentAsLong");
536 object typedValue = InternalReadContentAsObject();
537 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
539 if (xmlType != null) {
540 return xmlType.ValueConverter.ToInt64(typedValue);
543 return XmlUntypedConverter.Untyped.ToInt64(typedValue);
546 catch (InvalidCastException e) {
547 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
549 catch (FormatException e) {
550 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
552 catch (OverflowException e) {
553 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
557 public override string ReadContentAsString() {
558 if (!CanReadContentAs(this.NodeType)) {
559 throw CreateReadContentAsException("ReadContentAsString");
561 object typedValue = InternalReadContentAsObject();
562 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType;
564 if (xmlType != null) {
565 return xmlType.ValueConverter.ToString(typedValue);
568 return typedValue as string;
571 catch (InvalidCastException e) {
572 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
574 catch (FormatException e) {
575 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
577 catch (OverflowException e) {
578 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
582 public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) {
583 if (!CanReadContentAs(this.NodeType)) {
584 throw CreateReadContentAsException("ReadContentAs");
586 string originalStringValue;
588 object typedValue = InternalReadContentAsObject(false, out originalStringValue);
590 XmlSchemaType xmlType = NodeType == XmlNodeType.Attribute ? AttributeXmlType : ElementXmlType; //
592 if (xmlType != null) {
593 // special-case convertions to DateTimeOffset; typedValue is by default a DateTime
594 // which cannot preserve time zone, so we need to convert from the original string
595 if (returnType == typeof(DateTimeOffset) && xmlType.Datatype is Datatype_dateTimeBase) {
596 typedValue = originalStringValue;
598 return xmlType.ValueConverter.ChangeType(typedValue, returnType);
601 return XmlUntypedConverter.Untyped.ChangeType(typedValue, returnType, namespaceResolver);
604 catch (FormatException e) {
605 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
607 catch (InvalidCastException e) {
608 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
610 catch (OverflowException e) {
611 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
615 public override object ReadElementContentAsObject() {
616 if (this.NodeType != XmlNodeType.Element) {
617 throw CreateReadElementContentAsException("ReadElementContentAsObject");
619 XmlSchemaType xmlType;
621 return InternalReadElementContentAsObject(out xmlType, true);
625 public override bool ReadElementContentAsBoolean() {
626 if (this.NodeType != XmlNodeType.Element) {
627 throw CreateReadElementContentAsException("ReadElementContentAsBoolean");
629 XmlSchemaType xmlType;
631 object typedValue = InternalReadElementContentAsObject(out xmlType);
634 if (xmlType != null) {
635 return xmlType.ValueConverter.ToBoolean(typedValue);
638 return XmlUntypedConverter.Untyped.ToBoolean(typedValue);
641 catch (FormatException e) {
642 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
644 catch (InvalidCastException e) {
645 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
647 catch (OverflowException e) {
648 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, this as IXmlLineInfo);
652 public override DateTime ReadElementContentAsDateTime() {
653 if (this.NodeType != XmlNodeType.Element) {
654 throw CreateReadElementContentAsException("ReadElementContentAsDateTime");
656 XmlSchemaType xmlType;
658 object typedValue = InternalReadElementContentAsObject(out xmlType);
661 if (xmlType != null) {
662 return xmlType.ValueConverter.ToDateTime(typedValue);
665 return XmlUntypedConverter.Untyped.ToDateTime(typedValue);
668 catch (FormatException e) {
669 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
671 catch (InvalidCastException e) {
672 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
674 catch (OverflowException e) {
675 throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, this as IXmlLineInfo);
679 public override double ReadElementContentAsDouble() {
680 if (this.NodeType != XmlNodeType.Element) {
681 throw CreateReadElementContentAsException("ReadElementContentAsDouble");
683 XmlSchemaType xmlType;
685 object typedValue = InternalReadElementContentAsObject(out xmlType);
688 if (xmlType != null) {
689 return xmlType.ValueConverter.ToDouble(typedValue);
692 return XmlUntypedConverter.Untyped.ToDouble(typedValue);
695 catch (FormatException e) {
696 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
698 catch (InvalidCastException e) {
699 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
701 catch (OverflowException e) {
702 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, this as IXmlLineInfo);
706 public override float ReadElementContentAsFloat() {
707 if (this.NodeType != XmlNodeType.Element) {
708 throw CreateReadElementContentAsException("ReadElementContentAsFloat");
710 XmlSchemaType xmlType;
712 object typedValue = InternalReadElementContentAsObject(out xmlType);
715 if (xmlType != null) {
716 return xmlType.ValueConverter.ToSingle(typedValue);
719 return XmlUntypedConverter.Untyped.ToSingle(typedValue);
722 catch (FormatException e) {
723 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
725 catch (InvalidCastException e) {
726 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
728 catch (OverflowException e) {
729 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, this as IXmlLineInfo);
733 public override Decimal ReadElementContentAsDecimal() {
734 if (this.NodeType != XmlNodeType.Element) {
735 throw CreateReadElementContentAsException("ReadElementContentAsDecimal");
737 XmlSchemaType xmlType;
739 object typedValue = InternalReadElementContentAsObject(out xmlType);
742 if (xmlType != null) {
743 return xmlType.ValueConverter.ToDecimal(typedValue);
746 return XmlUntypedConverter.Untyped.ToDecimal(typedValue);
749 catch (FormatException e) {
750 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
752 catch (InvalidCastException e) {
753 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
755 catch (OverflowException e) {
756 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, this as IXmlLineInfo);
760 public override int ReadElementContentAsInt() {
761 if (this.NodeType != XmlNodeType.Element) {
762 throw CreateReadElementContentAsException("ReadElementContentAsInt");
764 XmlSchemaType xmlType;
766 object typedValue = InternalReadElementContentAsObject(out xmlType);
769 if (xmlType != null) {
770 return xmlType.ValueConverter.ToInt32(typedValue);
773 return XmlUntypedConverter.Untyped.ToInt32(typedValue);
776 catch (FormatException e) {
777 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
779 catch (InvalidCastException e) {
780 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
782 catch (OverflowException e) {
783 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int", e, this as IXmlLineInfo);
787 public override long ReadElementContentAsLong() {
788 if (this.NodeType != XmlNodeType.Element) {
789 throw CreateReadElementContentAsException("ReadElementContentAsLong");
791 XmlSchemaType xmlType;
793 object typedValue = InternalReadElementContentAsObject(out xmlType);
796 if (xmlType != null) {
797 return xmlType.ValueConverter.ToInt64(typedValue);
800 return XmlUntypedConverter.Untyped.ToInt64(typedValue);
803 catch (FormatException e) {
804 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
806 catch (InvalidCastException e) {
807 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
809 catch (OverflowException e) {
810 throw new XmlException(Res.Xml_ReadContentAsFormatException, "Long", e, this as IXmlLineInfo);
814 public override string ReadElementContentAsString() {
815 if (this.NodeType != XmlNodeType.Element) {
816 throw CreateReadElementContentAsException("ReadElementContentAsString");
818 XmlSchemaType xmlType;
820 object typedValue = InternalReadElementContentAsObject(out xmlType);
823 if (xmlType != null) {
824 return xmlType.ValueConverter.ToString(typedValue);
827 return typedValue as string;
830 catch (InvalidCastException e) {
831 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
833 catch (FormatException e) {
834 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
836 catch (OverflowException e) {
837 throw new XmlException(Res.Xml_ReadContentAsFormatException, "String", e, this as IXmlLineInfo);
841 public override object ReadElementContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) {
842 if (this.NodeType != XmlNodeType.Element) {
843 throw CreateReadElementContentAsException("ReadElementContentAs");
845 XmlSchemaType xmlType;
846 string originalStringValue;
848 object typedValue = InternalReadElementContentAsObject(out xmlType, false, out originalStringValue);
851 if (xmlType != null) {
852 // special-case convertions to DateTimeOffset; typedValue is by default a DateTime
853 // which cannot preserve time zone, so we need to convert from the original string
854 if (returnType == typeof(DateTimeOffset) && xmlType.Datatype is Datatype_dateTimeBase) {
855 typedValue = originalStringValue;
857 return xmlType.ValueConverter.ChangeType(typedValue, returnType, namespaceResolver);
860 return XmlUntypedConverter.Untyped.ChangeType(typedValue, returnType, namespaceResolver);
863 catch (FormatException e) {
864 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
866 catch (InvalidCastException e) {
867 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
869 catch (OverflowException e) {
870 throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, this as IXmlLineInfo);
874 // Attribute Accessors
876 // The number of attributes on the current node.
877 public override int AttributeCount {
879 return attributeCount;
883 // Gets the value of the attribute with the specified Name.
884 public override string GetAttribute(string name) {
885 string attValue = coreReader.GetAttribute(name);
887 if (attValue == null && attributeCount > 0) { //Could be default attribute
888 ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, false);
889 if (defaultNode != null) { //Default found
890 attValue = defaultNode.RawValue;
896 // Gets the value of the attribute with the specified LocalName and NamespaceURI.
897 public override string GetAttribute(string name, string namespaceURI) {
898 string attValue = coreReader.GetAttribute(name, namespaceURI);
900 if (attValue == null && attributeCount > 0) { //Could be default attribute
901 namespaceURI = (namespaceURI == null) ? string.Empty : coreReaderNameTable.Get(namespaceURI);
902 name = coreReaderNameTable.Get(name);
903 if (name == null || namespaceURI == null) { //Attribute not present since we did not see it
906 ValidatingReaderNodeData attNode = GetDefaultAttribute(name, namespaceURI, false);
907 if (attNode != null) {
908 return attNode.RawValue;
914 // Gets the value of the attribute with the specified index.
915 public override string GetAttribute(int i) {
916 if (attributeCount == 0) {
919 if (i < coreReaderAttributeCount) {
920 return coreReader.GetAttribute(i);
923 int defaultIndex = i - coreReaderAttributeCount;
924 ValidatingReaderNodeData attNode = (ValidatingReaderNodeData)defaultAttributes[defaultIndex];
925 Debug.Assert(attNode != null);
926 return attNode.RawValue;
930 // Moves to the attribute with the specified Name
931 public override bool MoveToAttribute(string name) {
933 if (coreReader.MoveToAttribute(name)) {
934 validationState = ValidatingReaderState.OnAttribute;
935 attributePSVI = GetAttributePSVI(name);
938 else if (attributeCount > 0) { //Default attribute
939 ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, true);
940 if (defaultNode != null) {
941 validationState = ValidatingReaderState.OnDefaultAttribute;
942 attributePSVI = defaultNode.AttInfo;
943 cachedNode = defaultNode;
949 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
950 readBinaryHelper.Finish();
951 validationState = savedState;
956 // Moves to the attribute with the specified LocalName and NamespaceURI
957 public override bool MoveToAttribute(string name, string ns) {
958 //Check atomized local name and ns
959 name = coreReaderNameTable.Get(name);
960 ns = ns != null ? coreReaderNameTable.Get(ns) : string.Empty;
961 if (name == null || ns == null) { //Name or ns not found in the nameTable, then attribute is not found
964 if (coreReader.MoveToAttribute(name, ns)) {
965 validationState = ValidatingReaderState.OnAttribute;
966 if (inlineSchemaParser == null) {
967 attributePSVI = GetAttributePSVI(name, ns);
968 Debug.Assert(attributePSVI != null);
970 else { //Parsing inline schema, no PSVI for schema attributes
971 attributePSVI = null;
975 else { //Default attribute
976 ValidatingReaderNodeData defaultNode = GetDefaultAttribute(name, ns, true);
977 if (defaultNode != null) {
978 attributePSVI = defaultNode.AttInfo;
979 cachedNode = defaultNode;
980 validationState = ValidatingReaderState.OnDefaultAttribute;
986 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
987 readBinaryHelper.Finish();
988 validationState = savedState;
993 // Moves to the attribute with the specified index
994 public override void MoveToAttribute(int i) {
995 if (i < 0 || i >= attributeCount) {
996 throw new ArgumentOutOfRangeException("i");
998 currentAttrIndex = i;
999 if (i < coreReaderAttributeCount) { //reader attribute
1000 coreReader.MoveToAttribute(i);
1001 if (inlineSchemaParser == null) {
1002 attributePSVI = attributePSVINodes[i];
1005 attributePSVI = null;
1007 validationState = ValidatingReaderState.OnAttribute;
1009 else { //default attribute
1010 int defaultIndex = i - coreReaderAttributeCount;
1011 cachedNode = (ValidatingReaderNodeData)defaultAttributes[defaultIndex];
1012 attributePSVI = cachedNode.AttInfo;
1013 validationState = ValidatingReaderState.OnDefaultAttribute;
1015 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
1016 readBinaryHelper.Finish();
1017 validationState = savedState;
1021 // Moves to the first attribute.
1022 public override bool MoveToFirstAttribute() {
1023 if (coreReader.MoveToFirstAttribute()) {
1024 currentAttrIndex = 0;
1025 if (inlineSchemaParser == null) {
1026 attributePSVI = attributePSVINodes[0];
1029 attributePSVI = null;
1031 validationState = ValidatingReaderState.OnAttribute;
1034 else if (defaultAttributes.Count > 0) { //check for default
1035 cachedNode = (ValidatingReaderNodeData)defaultAttributes[0];
1036 attributePSVI = cachedNode.AttInfo;
1037 currentAttrIndex = 0;
1038 validationState = ValidatingReaderState.OnDefaultAttribute;
1043 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
1044 readBinaryHelper.Finish();
1045 validationState = savedState;
1050 // Moves to the next attribute.
1051 public override bool MoveToNextAttribute() {
1052 if (currentAttrIndex + 1 < coreReaderAttributeCount) {
1053 bool moveTo = coreReader.MoveToNextAttribute();
1054 Debug.Assert(moveTo);
1056 if (inlineSchemaParser == null) {
1057 attributePSVI = attributePSVINodes[currentAttrIndex];
1060 attributePSVI = null;
1062 validationState = ValidatingReaderState.OnAttribute;
1065 else if (currentAttrIndex + 1 < attributeCount) { //default attribute
1066 int defaultIndex = ++currentAttrIndex - coreReaderAttributeCount;
1067 cachedNode = (ValidatingReaderNodeData)defaultAttributes[defaultIndex];
1068 attributePSVI = cachedNode.AttInfo;
1069 validationState = ValidatingReaderState.OnDefaultAttribute;
1074 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
1075 readBinaryHelper.Finish();
1076 validationState = savedState;
1081 // Moves to the element that contains the current attribute node.
1082 public override bool MoveToElement() {
1083 if (coreReader.MoveToElement() || (int)validationState < 0) { //states OnDefaultAttribute or OnReadAttributeValue
1084 currentAttrIndex = -1;
1085 validationState = ValidatingReaderState.ClearAttributes;
1091 // Reads the next node from the stream/TextReader.
1092 public override bool Read() {
1093 switch (validationState) {
1094 case ValidatingReaderState.Read:
1095 if (coreReader.Read()) {
1096 ProcessReaderEvent();
1100 validator.EndValidation();
1101 if (coreReader.EOF) {
1102 validationState = ValidatingReaderState.EOF;
1107 case ValidatingReaderState.ParseInlineSchema:
1108 ProcessInlineSchema();
1111 case ValidatingReaderState.OnAttribute:
1112 case ValidatingReaderState.OnDefaultAttribute:
1113 case ValidatingReaderState.ClearAttributes:
1114 case ValidatingReaderState.OnReadAttributeValue:
1115 ClearAttributesInfo();
1116 if (inlineSchemaParser != null) {
1117 validationState = ValidatingReaderState.ParseInlineSchema;
1118 goto case ValidatingReaderState.ParseInlineSchema;
1121 validationState = ValidatingReaderState.Read;
1122 goto case ValidatingReaderState.Read;
1125 case ValidatingReaderState.ReadAhead: //Will enter here on calling Skip()
1126 ClearAttributesInfo();
1127 ProcessReaderEvent();
1128 validationState = ValidatingReaderState.Read;
1131 case ValidatingReaderState.OnReadBinaryContent:
1132 validationState = savedState;
1133 readBinaryHelper.Finish();
1136 case ValidatingReaderState.Init:
1137 validationState = ValidatingReaderState.Read;
1138 if (coreReader.ReadState == ReadState.Interactive) { //If the underlying reader is already positioned on a ndoe, process it
1139 ProcessReaderEvent();
1143 goto case ValidatingReaderState.Read;
1146 case ValidatingReaderState.ReaderClosed:
1147 case ValidatingReaderState.EOF:
1155 // Gets a value indicating whether XmlReader is positioned at the end of the stream/TextReader.
1156 public override bool EOF {
1158 return coreReader.EOF;
1162 // Closes the stream, changes the ReadState to Closed, and sets all the properties back to zero.
1163 public override void Close() {
1165 validationState = ValidatingReaderState.ReaderClosed;
1168 // Returns the read state of the XmlReader.
1169 public override ReadState ReadState {
1171 return (validationState == ValidatingReaderState.Init) ? ReadState.Initial : coreReader.ReadState;
1175 // Skips to the end tag of the current element.
1176 public override void Skip() {
1177 int startDepth = Depth;
1179 case XmlNodeType.Element:
1180 if (coreReader.IsEmptyElement) {
1183 bool callSkipToEndElem = true;
1184 //If union and unionValue has been parsed till EndElement, then validator.ValidateEndElement has been called
1185 //Hence should not call SkipToEndElement as the current context has already been popped in the validator
1186 if ((xmlSchemaInfo.IsUnionType || xmlSchemaInfo.IsDefault) && coreReader is XsdCachingReader) {
1187 callSkipToEndElem = false;
1190 validationState = ValidatingReaderState.ReadAhead;
1191 if (callSkipToEndElem) {
1192 validator.SkipToEndElement(xmlSchemaInfo);
1196 case XmlNodeType.Attribute:
1198 goto case XmlNodeType.Element;
1200 //For all other NodeTypes Skip() same as Read()
1205 // Gets the XmlNameTable associated with this implementation.
1206 public override XmlNameTable NameTable {
1208 return coreReaderNameTable;
1212 // Resolves a namespace prefix in the current element's scope.
1213 public override string LookupNamespace(string prefix) {
1214 return thisNSResolver.LookupNamespace(prefix);
1217 // Resolves the entity reference for nodes of NodeType EntityReference.
1218 public override void ResolveEntity() {
1219 throw new InvalidOperationException();
1222 // Parses the attribute value into one or more Text and/or EntityReference node types.
1223 public override bool ReadAttributeValue() {
1224 if (validationState == ValidatingReaderState.OnReadBinaryContent) {
1225 readBinaryHelper.Finish();
1226 validationState = savedState;
1228 if (NodeType == XmlNodeType.Attribute) {
1229 if (validationState == ValidatingReaderState.OnDefaultAttribute) {
1230 cachedNode = CreateDummyTextNode(cachedNode.RawValue, cachedNode.Depth + 1);
1231 validationState = ValidatingReaderState.OnReadAttributeValue;
1234 return coreReader.ReadAttributeValue();
1239 public override bool CanReadBinaryContent {
1245 public override int ReadContentAsBase64(byte[] buffer, int index, int count) {
1246 if (ReadState != ReadState.Interactive) {
1250 // init ReadContentAsBinaryHelper when called first time
1251 if (validationState != ValidatingReaderState.OnReadBinaryContent) {
1252 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
1253 savedState = validationState;
1256 // restore original state in order to have a normal Read() behavior when called from readBinaryHelper
1257 validationState = savedState;
1259 // call to the helper
1260 int readCount = readBinaryHelper.ReadContentAsBase64(buffer, index, count);
1262 // set OnReadBinaryContent state again and return
1263 savedState = validationState;
1264 validationState = ValidatingReaderState.OnReadBinaryContent;
1268 public override int ReadContentAsBinHex(byte[] buffer, int index, int count) {
1269 if (ReadState != ReadState.Interactive) {
1273 // init ReadContentAsBinaryHelper when called first time
1274 if (validationState != ValidatingReaderState.OnReadBinaryContent) {
1275 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
1276 savedState = validationState;
1279 // restore original state in order to have a normal Read() behavior when called from readBinaryHelper
1280 validationState = savedState;
1282 // call to the helper
1283 int readCount = readBinaryHelper.ReadContentAsBinHex(buffer, index, count);
1285 // set OnReadBinaryContent state again and return
1286 savedState = validationState;
1287 validationState = ValidatingReaderState.OnReadBinaryContent;
1291 public override int ReadElementContentAsBase64(byte[] buffer, int index, int count) {
1292 if (ReadState != ReadState.Interactive) {
1296 // init ReadContentAsBinaryHelper when called first time
1297 if (validationState != ValidatingReaderState.OnReadBinaryContent) {
1298 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
1299 savedState = validationState;
1302 // restore original state in order to have a normal Read() behavior when called from readBinaryHelper
1303 validationState = savedState;
1305 // call to the helper
1306 int readCount = readBinaryHelper.ReadElementContentAsBase64(buffer, index, count);
1308 // set OnReadBinaryContent state again and return
1309 savedState = validationState;
1310 validationState = ValidatingReaderState.OnReadBinaryContent;
1314 public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count) {
1315 if (ReadState != ReadState.Interactive) {
1319 // init ReadContentAsBinaryHelper when called first time
1320 if (validationState != ValidatingReaderState.OnReadBinaryContent) {
1321 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
1322 savedState = validationState;
1325 // restore original state in order to have a normal Read() behavior when called from readBinaryHelper
1326 validationState = savedState;
1328 // call to the helper
1329 int readCount = readBinaryHelper.ReadElementContentAsBinHex(buffer, index, count);
1331 // set OnReadBinaryContent state again and return
1332 savedState = validationState;
1333 validationState = ValidatingReaderState.OnReadBinaryContent;
1338 // IXmlSchemaInfo interface
1340 bool IXmlSchemaInfo.IsDefault {
1343 case XmlNodeType.Element:
1344 if (!coreReader.IsEmptyElement) {
1347 return xmlSchemaInfo.IsDefault;
1349 case XmlNodeType.EndElement:
1350 return xmlSchemaInfo.IsDefault;
1352 case XmlNodeType.Attribute:
1353 if (attributePSVI != null) {
1354 return AttributeSchemaInfo.IsDefault;
1365 bool IXmlSchemaInfo.IsNil {
1368 case XmlNodeType.Element:
1369 case XmlNodeType.EndElement:
1370 return xmlSchemaInfo.IsNil;
1379 XmlSchemaValidity IXmlSchemaInfo.Validity {
1382 case XmlNodeType.Element:
1383 if (coreReader.IsEmptyElement) {
1384 return xmlSchemaInfo.Validity;
1386 if (xmlSchemaInfo.Validity == XmlSchemaValidity.Valid) { //It might be valid for unions since we read ahead, but report notknown for consistency
1387 return XmlSchemaValidity.NotKnown;
1389 return xmlSchemaInfo.Validity;
1391 case XmlNodeType.EndElement:
1392 return xmlSchemaInfo.Validity;
1394 case XmlNodeType.Attribute:
1395 if (attributePSVI != null) {
1396 return AttributeSchemaInfo.Validity;
1400 return XmlSchemaValidity.NotKnown;
1404 XmlSchemaSimpleType IXmlSchemaInfo.MemberType {
1407 case XmlNodeType.Element:
1408 if (!coreReader.IsEmptyElement) {
1411 return xmlSchemaInfo.MemberType;
1413 case XmlNodeType.EndElement:
1414 return xmlSchemaInfo.MemberType;
1416 case XmlNodeType.Attribute:
1417 if (attributePSVI != null) {
1418 return AttributeSchemaInfo.MemberType;
1423 return null; //Text, PI, Comment etc
1428 XmlSchemaType IXmlSchemaInfo.SchemaType {
1431 case XmlNodeType.Element:
1432 case XmlNodeType.EndElement:
1433 return xmlSchemaInfo.SchemaType;
1435 case XmlNodeType.Attribute:
1436 if (attributePSVI != null) {
1437 return AttributeSchemaInfo.SchemaType;
1442 return null; //Text, PI, Comment etc
1446 XmlSchemaElement IXmlSchemaInfo.SchemaElement {
1448 if (NodeType == XmlNodeType.Element || NodeType == XmlNodeType.EndElement) {
1449 return xmlSchemaInfo.SchemaElement;
1455 XmlSchemaAttribute IXmlSchemaInfo.SchemaAttribute {
1457 if (NodeType == XmlNodeType.Attribute) {
1458 if (attributePSVI != null) {
1459 return AttributeSchemaInfo.SchemaAttribute;
1467 // IXmlLineInfo members
1470 public bool HasLineInfo() {
1474 public int LineNumber {
1476 if (lineInfo != null) {
1477 return lineInfo.LineNumber;
1483 public int LinePosition {
1485 if (lineInfo != null) {
1486 return lineInfo.LinePosition;
1493 // IXmlNamespaceResolver members
1495 IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) {
1496 if (coreReaderNSResolver != null) {
1497 return coreReaderNSResolver.GetNamespacesInScope(scope);
1500 return nsManager.GetNamespacesInScope(scope);
1504 string IXmlNamespaceResolver.LookupNamespace(string prefix) {
1505 if (coreReaderNSResolver != null) {
1506 return coreReaderNSResolver.LookupNamespace(prefix);
1509 return nsManager.LookupNamespace(prefix);
1513 string IXmlNamespaceResolver.LookupPrefix(string namespaceName) {
1514 if (coreReaderNSResolver != null) {
1515 return coreReaderNSResolver.LookupPrefix(namespaceName);
1518 return nsManager.LookupPrefix(namespaceName);
1522 //Internal / Private methods
1524 private object GetStringValue() {
1525 return coreReader.Value;
1528 private XmlSchemaType ElementXmlType {
1530 return xmlSchemaInfo.XmlType;
1534 private XmlSchemaType AttributeXmlType {
1536 if (attributePSVI != null) {
1537 return AttributeSchemaInfo.XmlType;
1543 private XmlSchemaInfo AttributeSchemaInfo {
1545 Debug.Assert(attributePSVI != null);
1546 return attributePSVI.attributeSchemaInfo;
1550 private void ProcessReaderEvent() {
1551 if (replayCache) { //if in replay mode, do nothing since nodes have been validated already
1552 //If NodeType == XmlNodeType.EndElement && if manageNamespaces, may need to pop namespace scope, since scope is not popped in ReadAheadForMemberType
1557 switch (coreReader.NodeType) {
1558 case XmlNodeType.Element:
1560 ProcessElementEvent();
1563 case XmlNodeType.Whitespace:
1564 case XmlNodeType.SignificantWhitespace:
1565 validator.ValidateWhitespace(GetStringValue);
1568 case XmlNodeType.Text: // text inside a node
1569 case XmlNodeType.CDATA: // <![CDATA[...]]>
1570 validator.ValidateText(GetStringValue);
1573 case XmlNodeType.EndElement:
1575 ProcessEndElementEvent();
1578 case XmlNodeType.EntityReference:
1579 throw new InvalidOperationException();
1581 case XmlNodeType.DocumentType:
1582 #if TEMP_HACK_FOR_SCHEMA_INFO
1583 validator.SetDtdSchemaInfo((SchemaInfo)coreReader.DtdInfo);
1585 validator.SetDtdSchemaInfo(coreReader.DtdInfo);
1595 // SxS: This function calls ValidateElement on XmlSchemaValidator which is annotated with ResourceExposure attribute.
1596 // Since the resource names (namespace location) are not provided directly by the user (they are read from the source
1597 // document) and the function does not expose any resources it is fine to suppress the SxS warning.
1598 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1599 [ResourceExposure(ResourceScope.None)]
1600 private void ProcessElementEvent() {
1601 if (this.processInlineSchema && IsXSDRoot(coreReader.LocalName, coreReader.NamespaceURI) && coreReader.Depth > 0) {
1602 xmlSchemaInfo.Clear();
1603 attributeCount = coreReaderAttributeCount = coreReader.AttributeCount;
1604 if (!coreReader.IsEmptyElement) { //If its not empty schema, then parse else ignore
1605 inlineSchemaParser = new Parser(SchemaType.XSD, coreReaderNameTable, validator.SchemaSet.GetSchemaNames(coreReaderNameTable), validationEvent);
1606 inlineSchemaParser.StartParsing(coreReader, null);
1607 inlineSchemaParser.ParseReaderNode();
1608 validationState = ValidatingReaderState.ParseInlineSchema;
1611 validationState = ValidatingReaderState.ClearAttributes;
1614 else { //Validate element
1616 //Clear previous data
1618 originalAtomicValueString = null;
1619 xmlSchemaInfo.Clear();
1621 if (manageNamespaces) {
1622 nsManager.PushScope();
1624 //Find Xsi attributes that need to be processed before validating the element
1625 string xsiSchemaLocation = null;
1626 string xsiNoNamespaceSL = null;
1627 string xsiNil = null;
1628 string xsiType = null;
1629 if (coreReader.MoveToFirstAttribute()) {
1631 string objectNs = coreReader.NamespaceURI;
1632 string objectName = coreReader.LocalName;
1633 if (Ref.Equal(objectNs, NsXsi)) {
1634 if (Ref.Equal(objectName, XsiSchemaLocation)) {
1635 xsiSchemaLocation = coreReader.Value;
1637 else if (Ref.Equal(objectName, XsiNoNamespaceSchemaLocation)) {
1638 xsiNoNamespaceSL = coreReader.Value;
1640 else if (Ref.Equal(objectName, XsiType)) {
1641 xsiType = coreReader.Value;
1643 else if (Ref.Equal(objectName, XsiNil)) {
1644 xsiNil = coreReader.Value;
1647 if (manageNamespaces && Ref.Equal(coreReader.NamespaceURI, NsXmlNs)) {
1648 nsManager.AddNamespace(coreReader.Prefix.Length == 0 ? string.Empty : coreReader.LocalName, coreReader.Value);
1651 } while (coreReader.MoveToNextAttribute());
1652 coreReader.MoveToElement();
1654 validator.ValidateElement(coreReader.LocalName, coreReader.NamespaceURI, xmlSchemaInfo, xsiType, xsiNil, xsiSchemaLocation, xsiNoNamespaceSL);
1655 ValidateAttributes();
1656 validator.ValidateEndOfAttributes(xmlSchemaInfo);
1657 if (coreReader.IsEmptyElement) {
1658 ProcessEndElementEvent();
1660 validationState = ValidatingReaderState.ClearAttributes;
1664 private void ProcessEndElementEvent() {
1665 atomicValue = validator.ValidateEndElement(xmlSchemaInfo);
1666 originalAtomicValueString = GetOriginalAtomicValueStringOfElement();
1667 if (xmlSchemaInfo.IsDefault) { //The atomicValue returned is a default value
1668 Debug.Assert(atomicValue != null);
1669 int depth = coreReader.Depth;
1670 coreReader = GetCachingReader();
1671 cachingReader.RecordTextNode( xmlSchemaInfo.XmlType.ValueConverter.ToString( atomicValue ), originalAtomicValueString, depth + 1, 0, 0 );
1672 cachingReader.RecordEndElementNode();
1673 cachingReader.SetToReplayMode();
1676 else if (manageNamespaces) {
1677 nsManager.PopScope();
1681 private void ValidateAttributes() {
1682 attributeCount = coreReaderAttributeCount = coreReader.AttributeCount;
1683 AttributePSVIInfo attributePSVI;
1685 bool attributeInvalid = false;
1686 if (coreReader.MoveToFirstAttribute()) {
1688 string localName = coreReader.LocalName;
1689 string ns = coreReader.NamespaceURI;
1691 attributePSVI = AddAttributePSVI(attIndex);
1692 attributePSVI.localName = localName;
1693 attributePSVI.namespaceUri = ns;
1695 if ((object)ns == (object)NsXmlNs) {
1699 attributePSVI.typedAttributeValue = validator.ValidateAttribute(localName, ns, valueGetter, attributePSVI.attributeSchemaInfo);
1700 if (!attributeInvalid) {
1701 attributeInvalid = attributePSVI.attributeSchemaInfo.Validity == XmlSchemaValidity.Invalid;
1705 } while (coreReader.MoveToNextAttribute());
1707 coreReader.MoveToElement();
1708 if (attributeInvalid) { //If any of the attributes are invalid, Need to report element's validity as invalid
1709 xmlSchemaInfo.Validity = XmlSchemaValidity.Invalid;
1711 validator.GetUnspecifiedDefaultAttributes(defaultAttributes, true);
1712 attributeCount += defaultAttributes.Count;
1715 private void ClearAttributesInfo() {
1717 coreReaderAttributeCount = 0;
1718 currentAttrIndex = -1;
1719 defaultAttributes.Clear();
1720 attributePSVI = null;
1723 private AttributePSVIInfo GetAttributePSVI(string name) {
1724 if (inlineSchemaParser != null) { //Parsing inline schema, no PSVI for schema attributes
1727 string attrLocalName;
1730 ValidateNames.SplitQName(name, out attrPrefix, out attrLocalName);
1731 attrPrefix = coreReaderNameTable.Add(attrPrefix);
1732 attrLocalName = coreReaderNameTable.Add(attrLocalName);
1734 if (attrPrefix.Length == 0) { //empty prefix, not qualified
1738 ns = thisNSResolver.LookupNamespace(attrPrefix);
1740 return GetAttributePSVI(attrLocalName, ns);
1743 private AttributePSVIInfo GetAttributePSVI(string localName, string ns) {
1744 Debug.Assert(coreReaderNameTable.Get(localName) != null);
1745 Debug.Assert(coreReaderNameTable.Get(ns) != null);
1746 AttributePSVIInfo attInfo = null;
1748 for (int i = 0; i < coreReaderAttributeCount; i++) {
1749 attInfo = attributePSVINodes[i];
1750 if (attInfo != null) { //Will be null for invalid attributes
1751 if (Ref.Equal(localName, attInfo.localName) && Ref.Equal(ns, attInfo.namespaceUri)) {
1752 currentAttrIndex = i;
1760 private ValidatingReaderNodeData GetDefaultAttribute(string name, bool updatePosition) {
1761 string attrLocalName;
1763 ValidateNames.SplitQName(name, out attrPrefix, out attrLocalName);
1766 attrPrefix = coreReaderNameTable.Add(attrPrefix);
1767 attrLocalName = coreReaderNameTable.Add(attrLocalName);
1769 if (attrPrefix.Length == 0) {
1773 ns = thisNSResolver.LookupNamespace(attrPrefix);
1775 return GetDefaultAttribute(attrLocalName, ns, updatePosition);
1778 private ValidatingReaderNodeData GetDefaultAttribute(string attrLocalName, string ns, bool updatePosition) {
1779 Debug.Assert(coreReaderNameTable.Get(attrLocalName) != null);
1780 Debug.Assert(coreReaderNameTable.Get(ns) != null);
1781 ValidatingReaderNodeData defaultNode = null;
1783 for (int i = 0; i < defaultAttributes.Count; i++) {
1784 defaultNode = (ValidatingReaderNodeData)defaultAttributes[i];
1785 if (Ref.Equal(defaultNode.LocalName, attrLocalName) && Ref.Equal(defaultNode.Namespace, ns)) {
1786 if (updatePosition) {
1787 currentAttrIndex = coreReader.AttributeCount + i;
1795 private AttributePSVIInfo AddAttributePSVI(int attIndex) {
1796 Debug.Assert(attIndex <= attributePSVINodes.Length);
1797 AttributePSVIInfo attInfo = attributePSVINodes[attIndex];
1798 if (attInfo != null) {
1802 if (attIndex >= attributePSVINodes.Length - 1) { //reached capacity of PSVIInfo array, Need to increase capacity to twice the initial
1803 AttributePSVIInfo[] newPSVINodes = new AttributePSVIInfo[attributePSVINodes.Length * 2];
1804 Array.Copy(attributePSVINodes, 0, newPSVINodes, 0, attributePSVINodes.Length);
1805 attributePSVINodes = newPSVINodes;
1807 attInfo = attributePSVINodes[attIndex];
1808 if (attInfo == null) {
1809 attInfo = new AttributePSVIInfo();
1810 attributePSVINodes[attIndex] = attInfo;
1815 private bool IsXSDRoot(string localName, string ns) {
1816 return Ref.Equal(ns, NsXs) && Ref.Equal(localName, XsdSchema);
1819 private void ProcessInlineSchema() {
1820 Debug.Assert(inlineSchemaParser != null);
1821 if (coreReader.Read()) {
1822 if (coreReader.NodeType == XmlNodeType.Element) {
1823 attributeCount = coreReaderAttributeCount = coreReader.AttributeCount;
1825 else { //Clear attributes info if nodeType is not element
1826 ClearAttributesInfo();
1828 if (!inlineSchemaParser.ParseReaderNode()) {
1829 inlineSchemaParser.FinishParsing();
1830 XmlSchema schema = inlineSchemaParser.XmlSchema;
1831 validator.AddSchema(schema);
1832 inlineSchemaParser = null;
1833 validationState = ValidatingReaderState.Read;
1838 private object InternalReadContentAsObject() {
1839 return InternalReadContentAsObject(false);
1842 private object InternalReadContentAsObject(bool unwrapTypedValue) {
1845 return InternalReadContentAsObject(unwrapTypedValue, out str);
1849 private object InternalReadContentAsObject(bool unwrapTypedValue, out string originalStringValue) {
1851 XmlNodeType nodeType = this.NodeType;
1852 if (nodeType == XmlNodeType.Attribute) {
1853 originalStringValue = this.Value;
1854 if ( attributePSVI != null && attributePSVI.typedAttributeValue != null ) {
1855 if ( validationState == ValidatingReaderState.OnDefaultAttribute) {
1856 XmlSchemaAttribute schemaAttr = attributePSVI.attributeSchemaInfo.SchemaAttribute;
1857 originalStringValue = ( schemaAttr.DefaultValue != null ) ? schemaAttr.DefaultValue : schemaAttr.FixedValue;
1860 return ReturnBoxedValue( attributePSVI.typedAttributeValue, AttributeSchemaInfo.XmlType, unwrapTypedValue );
1863 else { //return string value
1869 else if (nodeType == XmlNodeType.EndElement) {
1870 if (atomicValue != null) {
1871 originalStringValue = originalAtomicValueString;
1877 originalStringValue = string.Empty;
1879 return string.Empty;
1883 else { //Positioned on text, CDATA, PI, Comment etc
1884 if (validator.CurrentContentType == XmlSchemaContentType.TextOnly) { //if current element is of simple type
1885 object value = ReturnBoxedValue(ReadTillEndElement(), xmlSchemaInfo.XmlType, unwrapTypedValue);
1886 originalStringValue = originalAtomicValueString;
1892 XsdCachingReader cachingReader = this.coreReader as XsdCachingReader;
1893 if ( cachingReader != null ) {
1894 originalStringValue = cachingReader.ReadOriginalContentAsString();
1897 originalStringValue = InternalReadContentAsString();
1900 return originalStringValue;
1906 private object InternalReadElementContentAsObject(out XmlSchemaType xmlType) {
1908 return InternalReadElementContentAsObject(out xmlType, false);
1912 private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, bool unwrapTypedValue) {
1915 return InternalReadElementContentAsObject(out xmlType, unwrapTypedValue, out tmpString);
1919 private object InternalReadElementContentAsObject(out XmlSchemaType xmlType, bool unwrapTypedValue, out string originalString) {
1921 Debug.Assert(this.NodeType == XmlNodeType.Element);
1922 object typedValue = null;
1924 //If its an empty element, can have default/fixed value
1925 if (this.IsEmptyElement) {
1926 if (xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) {
1927 typedValue = ReturnBoxedValue(atomicValue, xmlSchemaInfo.XmlType, unwrapTypedValue);
1930 typedValue = atomicValue;
1932 originalString = originalAtomicValueString;
1933 xmlType = ElementXmlType; //Set this for default values
1939 // move to content and read typed value
1942 if (this.NodeType == XmlNodeType.EndElement) { //If IsDefault is true, the next node will be EndElement
1943 if (xmlSchemaInfo.IsDefault) {
1944 if (xmlSchemaInfo.ContentType == XmlSchemaContentType.TextOnly) {
1945 typedValue = ReturnBoxedValue(atomicValue, xmlSchemaInfo.XmlType, unwrapTypedValue);
1947 else { //anyType has default value
1948 typedValue = atomicValue;
1950 originalString = originalAtomicValueString;
1952 else { //Empty content
1953 typedValue = string.Empty;
1954 originalString = string.Empty;
1957 else if (this.NodeType == XmlNodeType.Element) { //the first child is again element node
1958 throw new XmlException(Res.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo);
1962 typedValue = InternalReadContentAsObject(unwrapTypedValue, out originalString);
1964 // ReadElementContentAsXXX cannot be called on mixed content, if positioned on node other than EndElement, Error
1965 if (this.NodeType != XmlNodeType.EndElement) {
1966 throw new XmlException(Res.Xml_MixedReadElementContentAs, string.Empty, this as IXmlLineInfo);
1969 xmlType = ElementXmlType; //Set this as we are moving ahead to the next node
1971 // move to next node
1978 private object ReadTillEndElement() {
1979 if (atomicValue == null) {
1980 while (coreReader.Read()) {
1981 if (replayCache) { //If replaying nodes in the cache, they have already been validated
1984 switch (coreReader.NodeType) {
1985 case XmlNodeType.Element:
1986 ProcessReaderEvent();
1989 case XmlNodeType.Text:
1990 case XmlNodeType.CDATA:
1991 validator.ValidateText(GetStringValue);
1994 case XmlNodeType.Whitespace:
1995 case XmlNodeType.SignificantWhitespace:
1996 validator.ValidateWhitespace(GetStringValue);
1999 case XmlNodeType.Comment:
2000 case XmlNodeType.ProcessingInstruction:
2003 case XmlNodeType.EndElement:
2004 atomicValue = validator.ValidateEndElement(xmlSchemaInfo);
2005 originalAtomicValueString = GetOriginalAtomicValueStringOfElement();
2006 if (manageNamespaces) {
2007 nsManager.PopScope();
2016 else { //atomicValue != null, meaning already read ahead - Switch reader
2017 if (atomicValue == this) { //switch back invalid marker; dont need it since coreReader moved to endElement
2025 private void SwitchReader() {
2026 XsdCachingReader cachingReader = this.coreReader as XsdCachingReader;
2027 if (cachingReader != null) { //Switch back without going over the cached contents again.
2028 this.coreReader = cachingReader.GetCoreReader();
2030 Debug.Assert(coreReader.NodeType == XmlNodeType.EndElement);
2031 replayCache = false;
2034 private void ReadAheadForMemberType() {
2035 while (coreReader.Read()) {
2036 switch (coreReader.NodeType) {
2037 case XmlNodeType.Element:
2038 Debug.Assert(false); //Should not happen as the caching reader does not cache elements in simple content
2041 case XmlNodeType.Text:
2042 case XmlNodeType.CDATA:
2043 validator.ValidateText(GetStringValue);
2046 case XmlNodeType.Whitespace:
2047 case XmlNodeType.SignificantWhitespace:
2048 validator.ValidateWhitespace(GetStringValue);
2051 case XmlNodeType.Comment:
2052 case XmlNodeType.ProcessingInstruction:
2055 case XmlNodeType.EndElement:
2056 atomicValue = validator.ValidateEndElement(xmlSchemaInfo); //?? pop namespaceManager scope
2057 originalAtomicValueString = GetOriginalAtomicValueStringOfElement();
2058 if (atomicValue == null) { //Invalid marker
2061 else if (xmlSchemaInfo.IsDefault) { //The atomicValue returned is a default value
2062 cachingReader.SwitchTextNodeAndEndElement(xmlSchemaInfo.XmlType.ValueConverter.ToString(atomicValue), originalAtomicValueString);
2072 private void GetIsDefault() {
2073 XsdCachingReader cachedReader = coreReader as XsdCachingReader;
2074 if (cachedReader == null && xmlSchemaInfo.HasDefaultValue) { //Get Isdefault
2075 coreReader = GetCachingReader();
2076 if (xmlSchemaInfo.IsUnionType && !xmlSchemaInfo.IsNil) { //If it also union, get the memberType as well
2077 ReadAheadForMemberType();
2080 if (coreReader.Read()) {
2081 switch (coreReader.NodeType) {
2082 case XmlNodeType.Element:
2083 Debug.Assert(false); //Should not happen as the caching reader does not cache elements in simple content
2086 case XmlNodeType.Text:
2087 case XmlNodeType.CDATA:
2088 validator.ValidateText(GetStringValue);
2091 case XmlNodeType.Whitespace:
2092 case XmlNodeType.SignificantWhitespace:
2093 validator.ValidateWhitespace(GetStringValue);
2096 case XmlNodeType.Comment:
2097 case XmlNodeType.ProcessingInstruction:
2100 case XmlNodeType.EndElement:
2101 atomicValue = validator.ValidateEndElement(xmlSchemaInfo); //?? pop namespaceManager scope
2102 originalAtomicValueString = GetOriginalAtomicValueStringOfElement();
2103 if (xmlSchemaInfo.IsDefault) { //The atomicValue returned is a default value
2104 cachingReader.SwitchTextNodeAndEndElement(xmlSchemaInfo.XmlType.ValueConverter.ToString(atomicValue), originalAtomicValueString);
2113 cachingReader.SetToReplayMode();
2118 private void GetMemberType() {
2119 if (xmlSchemaInfo.MemberType != null || atomicValue == this) {
2122 XsdCachingReader cachedReader = coreReader as XsdCachingReader;
2123 if (cachedReader == null && xmlSchemaInfo.IsUnionType && !xmlSchemaInfo.IsNil) {
2124 coreReader = GetCachingReader();
2125 ReadAheadForMemberType();
2126 cachingReader.SetToReplayMode();
2131 private object ReturnBoxedValue(object typedValue, XmlSchemaType xmlType, bool unWrap) {
2132 if (typedValue != null) {
2133 if (unWrap) { //convert XmlAtomicValue[] to object[] for list of unions; The other cases return typed value of the valueType anyway
2134 Debug.Assert(xmlType != null && xmlType.Datatype != null);
2135 if (xmlType.Datatype.Variety == XmlSchemaDatatypeVariety.List) {
2136 Datatype_List listType = xmlType.Datatype as Datatype_List;
2137 if (listType.ItemType.Variety == XmlSchemaDatatypeVariety.Union) {
2138 typedValue = xmlType.ValueConverter.ChangeType(typedValue, xmlType.Datatype.ValueType, thisNSResolver);
2144 else { //return the original string value of the element or attribute
2145 Debug.Assert(NodeType != XmlNodeType.Attribute);
2146 typedValue = validator.GetConcatenatedValue();
2151 private XsdCachingReader GetCachingReader() {
2152 if (cachingReader == null) {
2153 cachingReader = new XsdCachingReader(coreReader, lineInfo, new CachingEventHandler(CachingCallBack));
2156 cachingReader.Reset(coreReader);
2158 this.lineInfo = cachingReader as IXmlLineInfo;
2159 return cachingReader;
2162 internal ValidatingReaderNodeData CreateDummyTextNode(string attributeValue, int depth) {
2163 if (textNode == null) {
2164 textNode = new ValidatingReaderNodeData(XmlNodeType.Text);
2166 textNode.Depth = depth;
2167 textNode.RawValue = attributeValue;
2171 internal void CachingCallBack(XsdCachingReader cachingReader) {
2172 this.coreReader = cachingReader.GetCoreReader(); //re-switch the core-reader after caching reader is done
2173 this.lineInfo = cachingReader.GetLineInfo();
2174 replayCache = false;
2177 private string GetOriginalAtomicValueStringOfElement() {
2178 if ( xmlSchemaInfo.IsDefault ) {
2179 XmlSchemaElement schemaElem = xmlSchemaInfo.SchemaElement;
2180 if ( schemaElem != null ) {
2181 return ( schemaElem.DefaultValue != null ) ? schemaElem.DefaultValue : schemaElem.FixedValue;
2185 return validator.GetConcatenatedValue();
2187 return string.Empty;