The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlValidatingReaderImpl

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlValidatingReaderImpl.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.IO;
  17. using System.Text;
  18. using System.Xml.Schema;
  19. using System.Collections;
  20. using System.Diagnostics;
  21. using System.Globalization;
  22. using System.Security.Policy;
  23. using System.Collections.Generic;
  24. using System.Security.Permissions;
  25. namespace System.Xml
  26. {
  27.     internal sealed class XmlValidatingReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver
  28.     {
  29.         //
  30.         // Private helper types
  31.         //
  32.         // ParsingFunction = what should the reader do when the next Read() is called
  33.         enum ParsingFunction
  34.         {
  35.             Read = 0,
  36.             Init,
  37.             ParseDtdFromContext,
  38.             ResolveEntityInternally,
  39.             InReadBinaryContent,
  40.             ReaderClosed,
  41.             Error,
  42.             None
  43.         }
  44.        
  45.         //
  46.         // Fields
  47.         //
  48.         // core text reader
  49.         XmlReader coreReader;
  50.         XmlTextReaderImpl coreReaderImpl;
  51.         IXmlNamespaceResolver coreReaderNSResolver;
  52.        
  53.         // validation
  54.         ValidationType validationType;
  55.         BaseValidator validator;
  56.        
  57.         #pragma warning disable 618
  58.         XmlSchemaCollection schemaCollection;
  59.         #pragma warning restore 618
  60.         bool processIdentityConstraints;
  61.        
  62.         // parsing function (state)
  63.         ParsingFunction parsingFunction = ParsingFunction.Init;
  64.        
  65.         // event handlers
  66.         ValidationEventHandler internalEventHandler;
  67.         ValidationEventHandler eventHandler;
  68.        
  69.         // misc
  70.         XmlParserContext parserContext;
  71.        
  72.         // helper for Read[Element]ContentAs{Base64,BinHex} methods
  73.         ReadContentAsBinaryHelper readBinaryHelper;
  74.        
  75.         // Outer XmlReader exposed to the user - either XmlValidatingReader or XmlValidatingReaderImpl (when created via XmlReader.Create).
  76.         // Virtual methods called from within XmlValidatingReaderImpl must be called on the outer reader so in case the user overrides
  77.         // some of the XmlValidatingReader methods we will call the overriden version.
  78.         XmlReader outerReader;
  79.        
  80.         //
  81.         // Constructors
  82.         //
  83.         // Initializes a new instance of XmlValidatingReaderImpl class with the specified XmlReader.
  84.         // This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
  85.         internal XmlValidatingReaderImpl(XmlReader reader)
  86.         {
  87.             outerReader = this;
  88.             coreReader = reader;
  89.             coreReaderNSResolver = reader as IXmlNamespaceResolver;
  90.             coreReaderImpl = reader as XmlTextReaderImpl;
  91.             if (coreReaderImpl == null) {
  92.                 XmlTextReader tr = reader as XmlTextReader;
  93.                 if (tr != null) {
  94.                     coreReaderImpl = tr.Impl;
  95.                 }
  96.             }
  97.             if (coreReaderImpl == null) {
  98.                 throw new ArgumentException(Res.GetString(Res.Arg_ExpectingXmlTextReader), "reader");
  99.             }
  100.             coreReaderImpl.EntityHandling = EntityHandling.ExpandEntities;
  101.             coreReaderImpl.XmlValidatingReaderCompatibilityMode = true;
  102.             this.processIdentityConstraints = true;
  103.            
  104.             #pragma warning disable 618
  105.             schemaCollection = new XmlSchemaCollection(coreReader.NameTable);
  106.             schemaCollection.XmlResolver = GetResolver();
  107.            
  108.             internalEventHandler = new ValidationEventHandler(InternalValidationCallback);
  109.             eventHandler = internalEventHandler;
  110.             coreReaderImpl.ValidationEventHandler = internalEventHandler;
  111.            
  112.             validationType = ValidationType.Auto;
  113.             SetupValidation(ValidationType.Auto);
  114.             #pragma warning restore 618
  115.            
  116.         }
  117.        
  118.         // Initializes a new instance of XmlValidatingReaderImpl class for parsing fragments with the specified string, fragment type and parser context
  119.         // This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
  120.         internal XmlValidatingReaderImpl(string xmlFragment, XmlNodeType fragType, XmlParserContext context) : this(new XmlTextReader(xmlFragment, fragType, context))
  121.         {
  122.             if (coreReader.BaseURI.Length > 0) {
  123.                 validator.BaseUri = GetResolver().ResolveUri(null, coreReader.BaseURI);
  124.             }
  125.            
  126.             if (context != null) {
  127.                 parsingFunction = ParsingFunction.ParseDtdFromContext;
  128.                 parserContext = context;
  129.             }
  130.         }
  131.        
  132.         // Initializes a new instance of XmlValidatingReaderImpl class for parsing fragments with the specified stream, fragment type and parser context
  133.         // This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
  134.         internal XmlValidatingReaderImpl(Stream xmlFragment, XmlNodeType fragType, XmlParserContext context) : this(new XmlTextReader(xmlFragment, fragType, context))
  135.         {
  136.             if (coreReader.BaseURI.Length > 0) {
  137.                 validator.BaseUri = GetResolver().ResolveUri(null, coreReader.BaseURI);
  138.             }
  139.            
  140.             if (context != null) {
  141.                 parsingFunction = ParsingFunction.ParseDtdFromContext;
  142.                 parserContext = context;
  143.             }
  144.         }
  145.        
  146.         // Initializes a new instance of XmlValidatingReaderImpl class with the specified arguments.
  147.         // This constructor is used when creating XmlValidatingReaderImpl reader via "XmlReader.Create(..)"
  148.         internal XmlValidatingReaderImpl(XmlReader reader, ValidationEventHandler settingsEventHandler, bool processIdentityConstraints)
  149.         {
  150.             outerReader = this;
  151.             coreReader = reader;
  152.             coreReaderImpl = reader as XmlTextReaderImpl;
  153.             if (coreReaderImpl == null) {
  154.                 XmlTextReader tr = reader as XmlTextReader;
  155.                 if (tr != null) {
  156.                     coreReaderImpl = tr.Impl;
  157.                 }
  158.             }
  159.             if (coreReaderImpl == null) {
  160.                 throw new ArgumentException(Res.GetString(Res.Arg_ExpectingXmlTextReader), "reader");
  161.             }
  162.             coreReaderImpl.XmlValidatingReaderCompatibilityMode = true;
  163.             coreReaderNSResolver = reader as IXmlNamespaceResolver;
  164.             this.processIdentityConstraints = processIdentityConstraints;
  165.            
  166.             #pragma warning disable 618
  167.            
  168.             schemaCollection = new XmlSchemaCollection(coreReader.NameTable);
  169.            
  170.             #pragma warning restore 618
  171.            
  172.             schemaCollection.XmlResolver = GetResolver();
  173.            
  174.             if (settingsEventHandler == null) {
  175.                 internalEventHandler = new ValidationEventHandler(InternalValidationCallback);
  176.                 eventHandler = internalEventHandler;
  177.                 coreReaderImpl.ValidationEventHandler = internalEventHandler;
  178.             }
  179.             else {
  180.                 eventHandler = settingsEventHandler;
  181.                 coreReaderImpl.ValidationEventHandler = settingsEventHandler;
  182.             }
  183.            
  184.             validationType = ValidationType.DTD;
  185.             SetupValidation(ValidationType.DTD);
  186.         }
  187.        
  188.         //
  189.         // XmlReader members
  190.         //
  191.         // Returns the current settings of the reader
  192.         public override XmlReaderSettings Settings {
  193.             get {
  194.                 XmlReaderSettings settings;
  195.                 if (coreReaderImpl.V1Compat) {
  196.                     settings = null;
  197.                 }
  198.                 else {
  199.                     settings = coreReader.Settings;
  200.                 }
  201.                 if (settings != null) {
  202.                     settings = settings.Clone();
  203.                 }
  204.                 else {
  205.                     settings = new XmlReaderSettings();
  206.                 }
  207.                 settings.ValidationType = ValidationType.DTD;
  208.                 if (!processIdentityConstraints) {
  209.                     settings.ValidationFlags &= ~XmlSchemaValidationFlags.ProcessIdentityConstraints;
  210.                 }
  211.                 settings.ReadOnly = true;
  212.                 return settings;
  213.             }
  214.         }
  215.        
  216.         // Returns the type of the current node.
  217.         public override XmlNodeType NodeType {
  218.             get { return coreReader.NodeType; }
  219.         }
  220.        
  221.         // Returns the name of the current node, including prefix.
  222.         public override string Name {
  223.             get { return coreReader.Name; }
  224.         }
  225.        
  226.         // Returns local name of the current node (without prefix)
  227.         public override string LocalName {
  228.             get { return coreReader.LocalName; }
  229.         }
  230.        
  231.         // Returns namespace name of the current node.
  232.         public override string NamespaceURI {
  233.             get { return coreReader.NamespaceURI; }
  234.         }
  235.        
  236.         // Returns prefix associated with the current node.
  237.         public override string Prefix {
  238.             get { return coreReader.Prefix; }
  239.         }
  240.        
  241.         // Returns true if the current node can have Value property != string.Empty.
  242.         public override bool HasValue {
  243.             get { return coreReader.HasValue; }
  244.         }
  245.        
  246.         // Returns the text value of the current node.
  247.         public override string Value {
  248.             get { return coreReader.Value; }
  249.         }
  250.        
  251.         // Returns the depth of the current node in the XML element stack
  252.         public override int Depth {
  253.             get { return coreReader.Depth; }
  254.         }
  255.        
  256.         // Returns the base URI of the current node.
  257.         public override string BaseURI {
  258.             get { return coreReader.BaseURI; }
  259.         }
  260.        
  261.         // Returns true if the current node is an empty element (for example, <MyElement/>).
  262.         public override bool IsEmptyElement {
  263.             get { return coreReader.IsEmptyElement; }
  264.         }
  265.        
  266.         // Returns true of the current node is a default attribute declared in DTD.
  267.         public override bool IsDefault {
  268.             get { return coreReader.IsDefault; }
  269.         }
  270.        
  271.         // Returns the quote character used in the current attribute declaration
  272.         public override char QuoteChar {
  273.             get { return coreReader.QuoteChar; }
  274.         }
  275.        
  276.         // Returns the current xml:space scope.
  277.         public override XmlSpace XmlSpace {
  278.             get { return coreReader.XmlSpace; }
  279.         }
  280.        
  281.         // Returns the current xml:lang scope.</para>
  282.         public override string XmlLang {
  283.             get { return coreReader.XmlLang; }
  284.         }
  285.        
  286.         // Returns the current read state of the reader
  287.         public override ReadState ReadState {
  288.             get { return (parsingFunction == ParsingFunction.Init) ? ReadState.Initial : coreReader.ReadState; }
  289.         }
  290.        
  291.         // Returns true if the reader reached end of the input data
  292.         public override bool EOF {
  293.             get { return coreReader.EOF; }
  294.         }
  295.        
  296.         // Returns the XmlNameTable associated with this XmlReader
  297.         public override XmlNameTable NameTable {
  298.             get { return coreReader.NameTable; }
  299.         }
  300.        
  301.         // Returns encoding of the XML document
  302.         internal Encoding Encoding {
  303.             get { return coreReaderImpl.Encoding; }
  304.         }
  305.        
  306.        
  307.         // Returns the number of attributes on the current node.
  308.         public override int AttributeCount {
  309.             get { return coreReader.AttributeCount; }
  310.         }
  311.        
  312.         // Returns value of an attribute with the specified Name
  313.         public override string GetAttribute(string name)
  314.         {
  315.             return coreReader.GetAttribute(name);
  316.         }
  317.        
  318.         // Returns value of an attribute with the specified LocalName and NamespaceURI
  319.         public override string GetAttribute(string localName, string namespaceURI)
  320.         {
  321.             return coreReader.GetAttribute(localName, namespaceURI);
  322.         }
  323.        
  324.         // Returns value of an attribute at the specified index (position)
  325.         public override string GetAttribute(int i)
  326.         {
  327.             return coreReader.GetAttribute(i);
  328.         }
  329.        
  330.         // Moves to an attribute with the specified Name
  331.         public override bool MoveToAttribute(string name)
  332.         {
  333.             if (!coreReader.MoveToAttribute(name)) {
  334.                 return false;
  335.             }
  336.             parsingFunction = ParsingFunction.Read;
  337.             return true;
  338.         }
  339.        
  340.         // Moves to an attribute with the specified LocalName and NamespceURI
  341.         public override bool MoveToAttribute(string localName, string namespaceURI)
  342.         {
  343.             if (!coreReader.MoveToAttribute(localName, namespaceURI)) {
  344.                 return false;
  345.             }
  346.             parsingFunction = ParsingFunction.Read;
  347.             return true;
  348.         }
  349.        
  350.         // Moves to an attribute at the specified index (position)
  351.         public override void MoveToAttribute(int i)
  352.         {
  353.             coreReader.MoveToAttribute(i);
  354.             parsingFunction = ParsingFunction.Read;
  355.         }
  356.        
  357.         // Moves to the first attribute of the current node
  358.         public override bool MoveToFirstAttribute()
  359.         {
  360.             if (!coreReader.MoveToFirstAttribute()) {
  361.                 return false;
  362.             }
  363.             parsingFunction = ParsingFunction.Read;
  364.             return true;
  365.         }
  366.        
  367.         // Moves to the next attribute of the current node
  368.         public override bool MoveToNextAttribute()
  369.         {
  370.             if (!coreReader.MoveToNextAttribute()) {
  371.                 return false;
  372.             }
  373.             parsingFunction = ParsingFunction.Read;
  374.             return true;
  375.         }
  376.        
  377.         // If on attribute, moves to the element that contains the attribute node
  378.         public override bool MoveToElement()
  379.         {
  380.             if (!coreReader.MoveToElement()) {
  381.                 return false;
  382.             }
  383.             parsingFunction = ParsingFunction.Read;
  384.             return true;
  385.         }
  386.        
  387.         // Reads and validated next node from the input data
  388.         public override bool Read()
  389.         {
  390.             switch (parsingFunction) {
  391.                 case ParsingFunction.Read:
  392.                     if (coreReader.Read()) {
  393.                         ProcessCoreReaderEvent();
  394.                         return true;
  395.                     }
  396.                     else {
  397.                         validator.CompleteValidation();
  398.                         return false;
  399.                     }
  400.                     break;
  401.                 case ParsingFunction.ParseDtdFromContext:
  402.                     parsingFunction = ParsingFunction.Read;
  403.                     ParseDtdFromParserContext();
  404.                     goto case ParsingFunction.Read;
  405.                     break;
  406.                 case ParsingFunction.Error:
  407.                 case ParsingFunction.ReaderClosed:
  408.                     return false;
  409.                 case ParsingFunction.Init:
  410.                     parsingFunction = ParsingFunction.Read;
  411.                     // this changes the value returned by ReadState
  412.                     if (coreReader.ReadState == ReadState.Interactive) {
  413.                         ProcessCoreReaderEvent();
  414.                         return true;
  415.                     }
  416.                     else {
  417.                         goto case ParsingFunction.Read;
  418.                     }
  419.                     break;
  420.                 case ParsingFunction.ResolveEntityInternally:
  421.                     parsingFunction = ParsingFunction.Read;
  422.                     ResolveEntityInternally();
  423.                     goto case ParsingFunction.Read;
  424.                     break;
  425.                 case ParsingFunction.InReadBinaryContent:
  426.                     parsingFunction = ParsingFunction.Read;
  427.                     readBinaryHelper.Finish();
  428.                     goto case ParsingFunction.Read;
  429.                     break;
  430.                 default:
  431.                     Debug.Assert(false);
  432.                     return false;
  433.             }
  434.         }
  435.        
  436.         // Closes the input stream ot TextReader, changes the ReadState to Closed and sets all properties to zero/string.Empty
  437.         public override void Close()
  438.         {
  439.             coreReader.Close();
  440.             parsingFunction = ParsingFunction.ReaderClosed;
  441.         }
  442.        
  443.         // Returns NamespaceURI associated with the specified prefix in the current namespace scope.
  444.         public override string LookupNamespace(string prefix)
  445.         {
  446.             return coreReaderImpl.LookupNamespace(prefix);
  447.         }
  448.        
  449.         // Iterates through the current attribute value's text and entity references chunks.
  450.         public override bool ReadAttributeValue()
  451.         {
  452.             if (parsingFunction == ParsingFunction.InReadBinaryContent) {
  453.                 parsingFunction = ParsingFunction.Read;
  454.                 readBinaryHelper.Finish();
  455.             }
  456.             if (!coreReader.ReadAttributeValue()) {
  457.                 return false;
  458.             }
  459.             parsingFunction = ParsingFunction.Read;
  460.             return true;
  461.         }
  462.        
  463.         public override bool CanReadBinaryContent {
  464.             get { return true; }
  465.         }
  466.        
  467.         public override int ReadContentAsBase64(byte[] buffer, int index, int count)
  468.         {
  469.             if (ReadState != ReadState.Interactive) {
  470.                 return 0;
  471.             }
  472.            
  473.             // init ReadChunkHelper if called the first time
  474.             if (parsingFunction != ParsingFunction.InReadBinaryContent) {
  475.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, outerReader);
  476.             }
  477.            
  478.             // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
  479.             parsingFunction = ParsingFunction.Read;
  480.            
  481.             // call to the helper
  482.             int readCount = readBinaryHelper.ReadContentAsBase64(buffer, index, count);
  483.            
  484.             // setup parsingFunction
  485.             parsingFunction = ParsingFunction.InReadBinaryContent;
  486.             return readCount;
  487.         }
  488.        
  489.         public override int ReadContentAsBinHex(byte[] buffer, int index, int count)
  490.         {
  491.             if (ReadState != ReadState.Interactive) {
  492.                 return 0;
  493.             }
  494.            
  495.             // init ReadChunkHelper when called first time
  496.             if (parsingFunction != ParsingFunction.InReadBinaryContent) {
  497.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, outerReader);
  498.             }
  499.            
  500.             // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
  501.             parsingFunction = ParsingFunction.Read;
  502.            
  503.             // call to the helper
  504.             int readCount = readBinaryHelper.ReadContentAsBinHex(buffer, index, count);
  505.            
  506.             // setup parsingFunction
  507.             parsingFunction = ParsingFunction.InReadBinaryContent;
  508.             return readCount;
  509.         }
  510.        
  511.         public override int ReadElementContentAsBase64(byte[] buffer, int index, int count)
  512.         {
  513.             if (ReadState != ReadState.Interactive) {
  514.                 return 0;
  515.             }
  516.            
  517.             // init ReadChunkHelper if called the first time
  518.             if (parsingFunction != ParsingFunction.InReadBinaryContent) {
  519.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, outerReader);
  520.             }
  521.            
  522.             // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
  523.             parsingFunction = ParsingFunction.Read;
  524.            
  525.             // call to the helper
  526.             int readCount = readBinaryHelper.ReadElementContentAsBase64(buffer, index, count);
  527.            
  528.             // setup parsingFunction
  529.             parsingFunction = ParsingFunction.InReadBinaryContent;
  530.             return readCount;
  531.         }
  532.        
  533.         public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count)
  534.         {
  535.             if (ReadState != ReadState.Interactive) {
  536.                 return 0;
  537.             }
  538.            
  539.             // init ReadChunkHelper when called first time
  540.             if (parsingFunction != ParsingFunction.InReadBinaryContent) {
  541.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, outerReader);
  542.             }
  543.            
  544.             // set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
  545.             parsingFunction = ParsingFunction.Read;
  546.            
  547.             // call to the helper
  548.             int readCount = readBinaryHelper.ReadElementContentAsBinHex(buffer, index, count);
  549.            
  550.             // setup parsingFunction
  551.             parsingFunction = ParsingFunction.InReadBinaryContent;
  552.             return readCount;
  553.         }
  554.        
  555.         // Returns true if the XmlReader knows how to resolve general entities
  556.         public override bool CanResolveEntity {
  557.             get { return true; }
  558.         }
  559.        
  560.         // Resolves the current entity reference node
  561.         public override void ResolveEntity()
  562.         {
  563.             if (parsingFunction == ParsingFunction.ResolveEntityInternally) {
  564.                 parsingFunction = ParsingFunction.Read;
  565.             }
  566.             coreReader.ResolveEntity();
  567.         }
  568.        
  569.         internal XmlReader OuterReader {
  570.             get { return outerReader; }
  571.             set {
  572.                 #pragma warning disable 618
  573.                 Debug.Assert(value is XmlValidatingReader);
  574.                 #pragma warning restore 618
  575.                 outerReader = value;
  576.             }
  577.         }
  578.        
  579.         internal void MoveOffEntityReference()
  580.         {
  581.             if (outerReader.NodeType == XmlNodeType.EntityReference && parsingFunction != ParsingFunction.ResolveEntityInternally) {
  582.                 if (!outerReader.Read()) {
  583.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  584.                 }
  585.             }
  586.         }
  587.        
  588.         public override string ReadString()
  589.         {
  590.             MoveOffEntityReference();
  591.             return base.ReadString();
  592.         }
  593.        
  594.         //
  595.         // IXmlLineInfo members
  596.         //
  597.         public bool HasLineInfo()
  598.         {
  599.             return true;
  600.         }
  601.        
  602.         // Returns the line number of the current node
  603.         public int LineNumber {
  604.             get { return ((IXmlLineInfo)coreReader).LineNumber; }
  605.         }
  606.        
  607.         // Returns the line number of the current node
  608.         public int LinePosition {
  609.             get { return ((IXmlLineInfo)coreReader).LinePosition; }
  610.         }
  611.        
  612.         //
  613.         // IXmlNamespaceResolver members
  614.         //
  615.         IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  616.         {
  617.             return this.GetNamespacesInScope(scope);
  618.         }
  619.        
  620.         string IXmlNamespaceResolver.LookupNamespace(string prefix)
  621.         {
  622.             return this.LookupNamespace(prefix);
  623.         }
  624.        
  625.         string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  626.         {
  627.             return this.LookupPrefix(namespaceName);
  628.         }
  629.        
  630.         // Internal IXmlNamespaceResolver methods
  631.         internal IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
  632.         {
  633.             return coreReaderNSResolver.GetNamespacesInScope(scope);
  634.         }
  635.        
  636.         internal string LookupPrefix(string namespaceName)
  637.         {
  638.             return coreReaderNSResolver.LookupPrefix(namespaceName);
  639.         }
  640.        
  641.         //
  642.         // XmlValidatingReader members
  643.         //
  644.         // Specufies the validation event handler that wil get warnings and errors related to validation
  645.         internal event ValidationEventHandler ValidationEventHandler {
  646.             add {
  647.                 eventHandler -= internalEventHandler;
  648.                 eventHandler += value;
  649.                 if (eventHandler == null) {
  650.                     eventHandler = internalEventHandler;
  651.                 }
  652.                 UpdateHandlers();
  653.             }
  654.             remove {
  655.                 eventHandler -= value;
  656.                 if (eventHandler == null) {
  657.                     eventHandler = internalEventHandler;
  658.                 }
  659.                 UpdateHandlers();
  660.             }
  661.         }
  662.        
  663.         // returns the schema type of the current node
  664.         internal object SchemaType {
  665.             get {
  666.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.SchemaType property cannot be accessed on reader created via XmlReader.Create.");
  667.                 if (validationType != ValidationType.None) {
  668.                     XmlSchemaType schemaTypeObj = coreReaderImpl.InternalSchemaType as XmlSchemaType;
  669.                     if (schemaTypeObj != null && schemaTypeObj.QualifiedName.Namespace == XmlReservedNs.NsXs) {
  670.                         return schemaTypeObj.Datatype;
  671.                     }
  672.                     return coreReaderImpl.InternalSchemaType;
  673.                 }
  674.                 else
  675.                     return null;
  676.             }
  677.         }
  678.        
  679.         // returns the underlying XmlTextReader or XmlTextReaderImpl
  680.         internal XmlReader Reader {
  681.             get { return (XmlReader)coreReader; }
  682.         }
  683.        
  684.         // returns the underlying XmlTextReaderImpl
  685.         internal XmlTextReaderImpl ReaderImpl {
  686.             get { return coreReaderImpl; }
  687.         }
  688.        
  689.         // specifies the validation type (None, DDT, XSD, XDR, Auto)
  690.         internal ValidationType ValidationType {
  691.             get {
  692.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.ValidationType property cannot be accessed on reader created via XmlReader.Create.");
  693.                 return validationType;
  694.             }
  695.             set {
  696.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.ValidationType property cannot be changed on reader created via XmlReader.Create.");
  697.                 if (ReadState != ReadState.Initial) {
  698.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  699.                 }
  700.                 validationType = value;
  701.                 SetupValidation(value);
  702.             }
  703.         }
  704.        
  705.         // current schema collection used for validationg
  706.         #pragma warning disable 618
  707.         internal XmlSchemaCollection Schemas {
  708.             get {
  709.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.Schemas property cannot be accessed on reader created via XmlReader.Create.");
  710.                 return schemaCollection;
  711.             }
  712.         }
  713.         #pragma warning restore 618
  714.        
  715.         // Spefifies whether general entities should be automatically expanded or not
  716.         internal EntityHandling EntityHandling {
  717.             get {
  718.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.EntityHandling property cannot be accessed on reader created via XmlReader.Create.");
  719.                 return coreReaderImpl.EntityHandling;
  720.             }
  721.             set {
  722.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.EntityHandling property cannot be changed on reader created via XmlReader.Create.");
  723.                 coreReaderImpl.EntityHandling = value;
  724.             }
  725.         }
  726.        
  727.         // Specifies XmlResolver used for opening the XML document and other external references
  728.         internal XmlResolver XmlResolver {
  729.             set {
  730.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.XmlResolver property cannot be changed on reader created via XmlReader.Create.");
  731.                 coreReaderImpl.XmlResolver = value;
  732.                 validator.XmlResolver = value;
  733.                 schemaCollection.XmlResolver = value;
  734.             }
  735.         }
  736.        
  737.         // Disables or enables support of W3C XML 1.0 Namespaces
  738.         internal bool Namespaces {
  739.             get {
  740.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.Namespaces property cannot be accessed on reader created via XmlReader.Create.");
  741.                 return coreReaderImpl.Namespaces;
  742.             }
  743.             set {
  744.                 Debug.Assert(coreReaderImpl.V1Compat, "XmlValidatingReaderImpl.Namespaces property cannot be changed on reader created via XmlReader.Create.");
  745.                 coreReaderImpl.Namespaces = value;
  746.             }
  747.         }
  748.        
  749.         // Returns typed value of the current node (based on the type specified by schema)
  750.         public object ReadTypedValue()
  751.         {
  752.             if (validationType == ValidationType.None) {
  753.                 return null;
  754.             }
  755.            
  756.             switch (outerReader.NodeType) {
  757.                 case XmlNodeType.Attribute:
  758.                     return coreReaderImpl.InternalTypedValue;
  759.                 case XmlNodeType.Element:
  760.                     if (SchemaType == null) {
  761.                         return null;
  762.                     }
  763.                     XmlSchemaDatatype dtype = (SchemaType is XmlSchemaDatatype) ? (XmlSchemaDatatype)SchemaType : ((XmlSchemaType)SchemaType).Datatype;
  764.                     if (dtype != null) {
  765.                         if (!outerReader.IsEmptyElement) {
  766.                             for (;;) {
  767.                                 if (!outerReader.Read()) {
  768.                                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  769.                                 }
  770.                                 XmlNodeType type = outerReader.NodeType;
  771.                                 if (type != XmlNodeType.CDATA && type != XmlNodeType.Text && type != XmlNodeType.Whitespace && type != XmlNodeType.SignificantWhitespace && type != XmlNodeType.Comment && type != XmlNodeType.ProcessingInstruction) {
  772.                                     break;
  773.                                 }
  774.                             }
  775.                             if (outerReader.NodeType != XmlNodeType.EndElement) {
  776.                                 throw new XmlException(Res.Xml_InvalidNodeType, outerReader.NodeType.ToString());
  777.                             }
  778.                         }
  779.                         return coreReaderImpl.InternalTypedValue;
  780.                     }
  781.                     return null;
  782.                 case XmlNodeType.EndElement:
  783.                    
  784.                     return null;
  785.                 default:
  786.                    
  787.                     if (coreReaderImpl.V1Compat) {
  788.                         //If v1 XmlValidatingReader return null
  789.                         return null;
  790.                     }
  791.                     else {
  792.                         return Value;
  793.                     }
  794.                     break;
  795.             }
  796.         }
  797.        
  798.         //
  799.         // Private implementation methods
  800.         //
  801.        
  802.         private void ParseDtdFromParserContext()
  803.         {
  804.             Debug.Assert(parserContext != null);
  805.             Debug.Assert(coreReaderImpl.DtdSchemaInfo == null);
  806.            
  807.             if (parserContext.DocTypeName == null || parserContext.DocTypeName.Length == 0) {
  808.                 return;
  809.             }
  810.            
  811.             coreReaderImpl.DtdSchemaInfo = DtdParser.Parse(coreReaderImpl, parserContext.BaseURI, parserContext.DocTypeName, parserContext.PublicId, parserContext.SystemId, parserContext.InternalSubset);
  812.             ValidateDtd();
  813.         }
  814.        
  815.         private void ValidateDtd()
  816.         {
  817.             SchemaInfo dtdSchemaInfo = coreReaderImpl.DtdSchemaInfo;
  818.             if (dtdSchemaInfo != null) {
  819.                 switch (validationType) {
  820.                     case ValidationType.Auto:
  821.                         #pragma warning disable 618
  822.                         SetupValidation(ValidationType.DTD);
  823.                         goto case ValidationType.DTD;
  824.                         break;
  825.                     case ValidationType.DTD:
  826.                     case ValidationType.None:
  827.                         #pragma warning restore 618
  828.                         validator.SchemaInfo = dtdSchemaInfo;
  829.                         break;
  830.                 }
  831.             }
  832.         }
  833.        
  834.         private void ResolveEntityInternally()
  835.         {
  836.             Debug.Assert(coreReader.NodeType == XmlNodeType.EntityReference);
  837.             int initialDepth = coreReader.Depth;
  838.             outerReader.ResolveEntity();
  839.             while (outerReader.Read() && coreReader.Depth > initialDepth)
  840.                 ;
  841.         }
  842.        
  843.         private void UpdateHandlers()
  844.         {
  845.             validator.EventHandler = eventHandler;
  846.             coreReaderImpl.ValidationEventHandler = (validationType != ValidationType.None) ? eventHandler : null;
  847.         }
  848.        
  849.         private void SetupValidation(ValidationType valType)
  850.         {
  851.             validator = BaseValidator.CreateInstance(valType, this, schemaCollection, eventHandler, processIdentityConstraints);
  852.            
  853.             XmlResolver resolver = GetResolver();
  854.             validator.XmlResolver = resolver;
  855.            
  856.             if (outerReader.BaseURI.Length > 0) {
  857.                 validator.BaseUri = (resolver == null) ? new Uri(outerReader.BaseURI, UriKind.RelativeOrAbsolute) : resolver.ResolveUri(null, outerReader.BaseURI);
  858.             }
  859.            
  860.             UpdateHandlers();
  861.         }
  862.        
  863.         // This is needed because we can't have the setter for XmlResolver public and with internal getter.
  864.         private XmlResolver GetResolver()
  865.         {
  866.             return coreReaderImpl.GetResolver();
  867.         }
  868.        
  869.         private void InternalValidationCallback(object sender, ValidationEventArgs e)
  870.         {
  871.             if (validationType != ValidationType.None && e.Severity == XmlSeverityType.Error) {
  872.                 throw e.Exception;
  873.             }
  874.         }
  875.        
  876.         //
  877.         // Internal methods for validators, DOM, XPathDocument etc.
  878.         //
  879.         private void ProcessCoreReaderEvent()
  880.         {
  881.             switch (coreReader.NodeType) {
  882.                 case XmlNodeType.Whitespace:
  883.                     if (coreReader.Depth > 0 || coreReaderImpl.FragmentType != XmlNodeType.Document) {
  884.                         if (validator.PreserveWhitespace) {
  885.                             coreReaderImpl.ChangeCurrentNodeType(XmlNodeType.SignificantWhitespace);
  886.                         }
  887.                     }
  888.                     goto default;
  889.                     break;
  890.                 case XmlNodeType.DocumentType:
  891.                     ValidateDtd();
  892.                     break;
  893.                 case XmlNodeType.EntityReference:
  894.                     parsingFunction = ParsingFunction.ResolveEntityInternally;
  895.                     goto default;
  896.                     break;
  897.                 default:
  898.                     coreReaderImpl.InternalSchemaType = null;
  899.                     coreReaderImpl.InternalTypedValue = null;
  900.                     validator.Validate();
  901.                     break;
  902.             }
  903.         }
  904.        
  905.         internal void Close(bool closeStream)
  906.         {
  907.             coreReaderImpl.Close(closeStream);
  908.             parsingFunction = ParsingFunction.ReaderClosed;
  909.         }
  910.        
  911.         internal BaseValidator Validator {
  912.             get { return validator; }
  913.             set { validator = value; }
  914.         }
  915.        
  916.         internal override XmlNamespaceManager NamespaceManager {
  917.             get { return coreReaderImpl.NamespaceManager; }
  918.         }
  919.        
  920.         internal bool StandAlone {
  921.             get { return coreReaderImpl.StandAlone; }
  922.         }
  923.        
  924.         internal object SchemaTypeObject {
  925.             set { coreReaderImpl.InternalSchemaType = value; }
  926.         }
  927.        
  928.         internal object TypedValueObject {
  929.             get { return coreReaderImpl.InternalTypedValue; }
  930.             set { coreReaderImpl.InternalTypedValue = value; }
  931.         }
  932.        
  933.         internal bool Normalization {
  934.             get { return coreReaderImpl.Normalization; }
  935.         }
  936.        
  937.         internal bool AddDefaultAttribute(SchemaAttDef attdef)
  938.         {
  939.             return coreReaderImpl.AddDefaultAttribute(attdef, false);
  940.         }
  941.        
  942.         internal SchemaInfo GetSchemaInfo()
  943.         {
  944.             return validator.SchemaInfo;
  945.         }
  946.     }
  947. }

Developer Fusion