|
//------------------------------------------------------------------------------
// <copyright file="XmlValidatingReaderImpl.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
using System;
using System.IO;
using System.Text;
using System.Xml.Schema;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Security.Policy;
using System.Collections.Generic;
using System.Security.Permissions;
using System.Runtime.Versioning;
namespace System.Xml
{
internal sealed partial class XmlValidatingReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver {
//
// Private helper types
//
// ParsingFunction = what should the reader do when the next Read() is called
enum ParsingFunction {
Read = 0,
Init,
ParseDtdFromContext,
ResolveEntityInternally,
InReadBinaryContent,
ReaderClosed,
Error,
None,
}
internal class ValidationEventHandling : IValidationEventHandling {
// Fields
XmlValidatingReaderImpl reader;
ValidationEventHandler eventHandler;
// Constructor
internal ValidationEventHandling(XmlValidatingReaderImpl reader) {
this.reader = reader;
}
// IValidationEventHandling interface
#region IValidationEventHandling interface
object IValidationEventHandling.EventHandler {
get { return eventHandler; }
}
void IValidationEventHandling.SendEvent(Exception /*XmlSchemaException*/ exception, XmlSeverityType severity) {
if (eventHandler != null) {
eventHandler(reader, new ValidationEventArgs((XmlSchemaException)exception, severity));
}
else if (reader.ValidationType != ValidationType.None && severity == XmlSeverityType.Error) {
throw exception;
}
}
#endregion
// XmlValidatingReaderImpl helper methods
internal void AddHandler(ValidationEventHandler handler) {
eventHandler += handler;
}
internal void RemoveHandler(ValidationEventHandler handler) {
eventHandler -= handler;
}
}
//
// Fields
//
// core text reader
XmlReader coreReader;
XmlTextReaderImpl coreReaderImpl;
IXmlNamespaceResolver coreReaderNSResolver;
// validation
ValidationType validationType;
BaseValidator validator;
#pragma warning disable 618
XmlSchemaCollection schemaCollection;
#pragma warning restore 618
bool processIdentityConstraints;
// parsing function (state)
ParsingFunction parsingFunction = ParsingFunction.Init;
// event handling
ValidationEventHandling eventHandling;
// misc
XmlParserContext parserContext;
// helper for Read[Element]ContentAs{Base64,BinHex} methods
ReadContentAsBinaryHelper readBinaryHelper;
// Outer XmlReader exposed to the user - either XmlValidatingReader or XmlValidatingReaderImpl (when created via XmlReader.Create).
// Virtual methods called from within XmlValidatingReaderImpl must be called on the outer reader so in case the user overrides
// some of the XmlValidatingReader methods we will call the overriden version.
XmlReader outerReader;
//
// Constructors
//
// Initializes a new instance of XmlValidatingReaderImpl class with the specified XmlReader.
// This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
internal XmlValidatingReaderImpl( XmlReader reader ) {
XmlAsyncCheckReader asyncCheckReader = reader as XmlAsyncCheckReader;
if (asyncCheckReader != null) {
reader = asyncCheckReader.CoreReader;
}
outerReader = this;
coreReader = reader;
coreReaderNSResolver = reader as IXmlNamespaceResolver;
coreReaderImpl = reader as XmlTextReaderImpl;
if ( coreReaderImpl == null ) {
XmlTextReader tr = reader as XmlTextReader;
if ( tr != null ) {
coreReaderImpl = tr.Impl;
}
}
if ( coreReaderImpl == null ) {
throw new ArgumentException( Res.GetString( Res.Arg_ExpectingXmlTextReader ), "reader" );
}
coreReaderImpl.EntityHandling = EntityHandling.ExpandEntities;
coreReaderImpl.XmlValidatingReaderCompatibilityMode = true;
this.processIdentityConstraints = true;
#pragma warning disable 618
schemaCollection = new XmlSchemaCollection( coreReader.NameTable );
schemaCollection.XmlResolver = GetResolver();
eventHandling = new ValidationEventHandling(this);
coreReaderImpl.ValidationEventHandling = eventHandling;
coreReaderImpl.OnDefaultAttributeUse = new XmlTextReaderImpl.OnDefaultAttributeUseDelegate(ValidateDefaultAttributeOnUse);
validationType = ValidationType.Auto;
SetupValidation( ValidationType.Auto );
#pragma warning restore 618
}
// Initializes a new instance of XmlValidatingReaderImpl class for parsing fragments with the specified string, fragment type and parser context
// This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
// SxS: This method resolves an Uri but does not expose it to the caller. It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
internal XmlValidatingReaderImpl( string xmlFragment, XmlNodeType fragType, XmlParserContext context )
: this( new XmlTextReader( xmlFragment, fragType, context ) )
{
if ( coreReader.BaseURI.Length > 0 ) {
validator.BaseUri = GetResolver().ResolveUri( null, coreReader.BaseURI );
}
if ( context != null ) {
parsingFunction = ParsingFunction.ParseDtdFromContext;
parserContext = context;
}
}
// Initializes a new instance of XmlValidatingReaderImpl class for parsing fragments with the specified stream, fragment type and parser context
// This constructor is used when creating XmlValidatingReaderImpl for V1 XmlValidatingReader
// SxS: This method resolves an Uri but does not expose it to the caller. It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
internal XmlValidatingReaderImpl( Stream xmlFragment, XmlNodeType fragType, XmlParserContext context )
: this( new XmlTextReader( xmlFragment, fragType, context ) )
{
if ( coreReader.BaseURI.Length > 0 ) {
validator.BaseUri = GetResolver().ResolveUri( null, coreReader.BaseURI );
}
if ( context != null ) {
parsingFunction = ParsingFunction.ParseDtdFromContext;
parserContext = context;
}
}
// Initializes a new instance of XmlValidatingReaderImpl class with the specified arguments.
// This constructor is used when creating XmlValidatingReaderImpl reader via "XmlReader.Create(..)"
internal XmlValidatingReaderImpl( XmlReader reader, ValidationEventHandler settingsEventHandler, bool processIdentityConstraints) {
XmlAsyncCheckReader asyncCheckReader = reader as XmlAsyncCheckReader;
if (asyncCheckReader != null) {
reader = asyncCheckReader.CoreReader;
}
outerReader = this;
coreReader = reader;
coreReaderImpl = reader as XmlTextReaderImpl;
if ( coreReaderImpl == null ) {
XmlTextReader tr = reader as XmlTextReader;
if ( tr != null ) {
coreReaderImpl = tr.Impl;
}
}
if ( coreReaderImpl == null ) {
throw new ArgumentException( Res.GetString( Res.Arg_ExpectingXmlTextReader ), "reader" );
}
coreReaderImpl.XmlValidatingReaderCompatibilityMode = true;
coreReaderNSResolver = reader as IXmlNamespaceResolver;
this.processIdentityConstraints = processIdentityConstraints;
#pragma warning disable 618
schemaCollection = new XmlSchemaCollection( coreReader.NameTable );
#pragma warning restore 618
schemaCollection.XmlResolver = GetResolver();
eventHandling = new ValidationEventHandling(this);
if (settingsEventHandler != null) {
eventHandling.AddHandler(settingsEventHandler);
}
coreReaderImpl.ValidationEventHandling = eventHandling;
coreReaderImpl.OnDefaultAttributeUse = new XmlTextReaderImpl.OnDefaultAttributeUseDelegate(ValidateDefaultAttributeOnUse);
validationType = ValidationType.DTD;
SetupValidation( ValidationType.DTD );
}
//
// XmlReader members
//
// Returns the current settings of the reader
public override XmlReaderSettings Settings {
get {
XmlReaderSettings settings;
if (coreReaderImpl.V1Compat) {
settings = null;
}
else {
settings = coreReader.Settings;
}
if (settings != null) {
settings = settings.Clone();
}
else {
settings = new XmlReaderSettings();
}
settings.ValidationType = ValidationType.DTD;
if (!processIdentityConstraints) {
settings.ValidationFlags &= ~XmlSchemaValidationFlags.ProcessIdentityConstraints;
}
settings.ReadOnly = true;
return settings;
}
}
// Returns the type of the current node.
public override XmlNodeType NodeType {
get {
return coreReader.NodeType;
}
}
// Returns the name of the current node, including prefix.
public override string Name {
get {
return coreReader.Name;
}
}
// Returns local name of the current node (without prefix)
public override string LocalName {
get {
return coreReader.LocalName;
}
}
// Returns namespace name of the current node.
public override string NamespaceURI {
get {
return coreReader.NamespaceURI;
}
}
// Returns prefix associated with the current node.
public override string Prefix {
get {
return coreReader.Prefix;
}
}
// Returns true if the current node can have Value property != string.Empty.
public override bool HasValue {
get {
return coreReader.HasValue;
}
}
// Returns the text value of the current node.
public override string Value {
get {
return coreReader.Value;
}
}
// Returns the depth of the current node in the XML element stack
public override int Depth {
get {
return coreReader.Depth;
}
}
// Returns the base URI of the current node.
public override string BaseURI {
get {
return coreReader.BaseURI;
}
}
// Returns true if the current node is an empty element (for example, <MyElement/>).
public override bool IsEmptyElement {
get {
return coreReader.IsEmptyElement;
}
}
// Returns true of the current node is a default attribute declared in DTD.
public override bool IsDefault {
get {
return coreReader.IsDefault;
}
}
// Returns the quote character used in the current attribute declaration
public override char QuoteChar {
get {
return coreReader.QuoteChar;
}
}
// Returns the current xml:space scope.
public override XmlSpace XmlSpace {
get {
return coreReader.XmlSpace;
}
}
// Returns the current xml:lang scope.</para>
public override string XmlLang {
get {
return coreReader.XmlLang;
}
}
// Returns the current read state of the reader
public override ReadState ReadState {
get {
return ( parsingFunction == ParsingFunction.Init ) ? ReadState.Initial : coreReader.ReadState;
}
}
// Returns true if the reader reached end of the input data
public override bool EOF {
get {
return coreReader.EOF;
}
}
// Returns the XmlNameTable associated with this XmlReader
public override XmlNameTable NameTable {
get {
return coreReader.NameTable;
}
}
// Returns encoding of the XML document
internal Encoding Encoding {
get {
return coreReaderImpl.Encoding;
}
}
// Returns the number of attributes on the current node.
public override int AttributeCount {
get {
return coreReader.AttributeCount;
}
}
// Returns value of an attribute with the specified Name
public override string GetAttribute( string name ) {
return coreReader.GetAttribute( name );
}
// Returns value of an attribute with the specified LocalName and NamespaceURI
public override string GetAttribute( string localName, string namespaceURI ) {
return coreReader.GetAttribute( localName, namespaceURI );
}
// Returns value of an attribute at the specified index (position)
public override string GetAttribute( int i ) {
return coreReader.GetAttribute( i );
}
// Moves to an attribute with the specified Name
public override bool MoveToAttribute( string name ) {
if ( !coreReader.MoveToAttribute( name ) ) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
// Moves to an attribute with the specified LocalName and NamespceURI
public override bool MoveToAttribute( string localName, string namespaceURI ) {
if ( !coreReader.MoveToAttribute( localName, namespaceURI ) ) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
// Moves to an attribute at the specified index (position)
public override void MoveToAttribute( int i ) {
coreReader.MoveToAttribute( i );
parsingFunction = ParsingFunction.Read;
}
// Moves to the first attribute of the current node
public override bool MoveToFirstAttribute() {
if ( !coreReader.MoveToFirstAttribute() ) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
// Moves to the next attribute of the current node
public override bool MoveToNextAttribute() {
if ( !coreReader.MoveToNextAttribute() ) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
// If on attribute, moves to the element that contains the attribute node
public override bool MoveToElement() {
if ( !coreReader.MoveToElement() ) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
// Reads and validated next node from the input data
public override bool Read() {
switch ( parsingFunction ) {
case ParsingFunction.Read:
if ( coreReader.Read() ) {
ProcessCoreReaderEvent();
return true;
}
else {
validator.CompleteValidation();
return false;
}
case ParsingFunction.ParseDtdFromContext:
parsingFunction = ParsingFunction.Read;
ParseDtdFromParserContext();
goto case ParsingFunction.Read;
case ParsingFunction.Error:
case ParsingFunction.ReaderClosed:
return false;
case ParsingFunction.Init:
parsingFunction = ParsingFunction.Read; // this changes the value returned by ReadState
if ( coreReader.ReadState == ReadState.Interactive ) {
ProcessCoreReaderEvent();
return true;
}
else {
goto case ParsingFunction.Read;
}
case ParsingFunction.ResolveEntityInternally:
parsingFunction = ParsingFunction.Read;
ResolveEntityInternally();
goto case ParsingFunction.Read;
case ParsingFunction.InReadBinaryContent:
parsingFunction = ParsingFunction.Read;
readBinaryHelper.Finish();
goto case ParsingFunction.Read;
default:
Debug.Assert( false );
return false;
}
}
// Closes the input stream ot TextReader, changes the ReadState to Closed and sets all properties to zero/string.Empty
public override void Close() {
coreReader.Close();
parsingFunction = ParsingFunction.ReaderClosed;
}
// Returns NamespaceURI associated with the specified prefix in the current namespace scope.
public override String LookupNamespace( String prefix ) {
return coreReaderImpl.LookupNamespace( prefix );
}
// Iterates through the current attribute value's text and entity references chunks.
public override bool ReadAttributeValue() {
if ( parsingFunction == ParsingFunction.InReadBinaryContent ) {
parsingFunction = ParsingFunction.Read;
readBinaryHelper.Finish();
}
if (!coreReader.ReadAttributeValue()) {
return false;
}
parsingFunction = ParsingFunction.Read;
return true;
}
public override bool CanReadBinaryContent {
get {
return true;
}
}
public override int ReadContentAsBase64( byte[] buffer, int index, int count ) {
if ( ReadState != ReadState.Interactive ) {
return 0;
}
// init ReadChunkHelper if called the first time
if ( parsingFunction != ParsingFunction.InReadBinaryContent ) {
readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader );
}
// set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
parsingFunction = ParsingFunction.Read;
// call to the helper
int readCount = readBinaryHelper.ReadContentAsBase64( buffer, index, count );
// setup parsingFunction
parsingFunction = ParsingFunction.InReadBinaryContent;
return readCount;
}
public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) {
if ( ReadState != ReadState.Interactive ) {
return 0;
}
// init ReadChunkHelper when called first time
if ( parsingFunction != ParsingFunction.InReadBinaryContent ) {
readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader );
}
// set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
parsingFunction = ParsingFunction.Read;
// call to the helper
int readCount = readBinaryHelper.ReadContentAsBinHex( buffer, index, count );
// setup parsingFunction
parsingFunction = ParsingFunction.InReadBinaryContent;
return readCount;
}
public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
if ( ReadState != ReadState.Interactive ) {
return 0;
}
// init ReadChunkHelper if called the first time
if ( parsingFunction != ParsingFunction.InReadBinaryContent ) {
readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader );
}
// set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
parsingFunction = ParsingFunction.Read;
// call to the helper
int readCount = readBinaryHelper.ReadElementContentAsBase64( buffer, index, count );
// setup parsingFunction
parsingFunction = ParsingFunction.InReadBinaryContent;
return readCount;
}
public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) {
if ( ReadState != ReadState.Interactive ) {
return 0;
}
// init ReadChunkHelper when called first time
if ( parsingFunction != ParsingFunction.InReadBinaryContent ) {
readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset( readBinaryHelper, outerReader );
}
// set parsingFunction to Read state in order to have a normal Read() behavior when called from readBinaryHelper
parsingFunction = ParsingFunction.Read;
// call to the helper
int readCount = readBinaryHelper.ReadElementContentAsBinHex( buffer, index, count );
// setup parsingFunction
parsingFunction = ParsingFunction.InReadBinaryContent;
return readCount;
}
// Returns true if the XmlReader knows how to resolve general entities
public override bool CanResolveEntity {
get {
return true;
}
}
// Resolves the current entity reference node
public override void ResolveEntity() {
if ( parsingFunction == ParsingFunction.ResolveEntityInternally ) {
parsingFunction = ParsingFunction.Read;
}
coreReader.ResolveEntity();
}
internal XmlReader OuterReader {
get {
return outerReader;
}
set {
#pragma warning disable 618
Debug.Assert( value is XmlValidatingReader );
#pragma warning restore 618
outerReader = value;
}
}
internal void MoveOffEntityReference() {
if ( outerReader.NodeType == XmlNodeType.EntityReference && parsingFunction != ParsingFunction.ResolveEntityInternally ) {
if ( !outerReader.Read() ) {
throw new InvalidOperationException( Res.GetString(Res.Xml_InvalidOperation ) );
}
}
}
public override string ReadString() {
MoveOffEntityReference();
return base.ReadString();
}
//
// IXmlLineInfo members
//
public bool HasLineInfo() {
return true;
}
// Returns the line number of the current node
public int LineNumber {
get {
return ((IXmlLineInfo)coreReader).LineNumber;
}
}
// Returns the line number of the current node
public int LinePosition {
get {
return ((IXmlLineInfo)coreReader).LinePosition;
}
}
//
// IXmlNamespaceResolver members
//
IDictionary<string,string> IXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) {
return this.GetNamespacesInScope( scope );
}
string IXmlNamespaceResolver.LookupNamespace(string prefix) {
return this.LookupNamespace( prefix );
}
string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) {
return this.LookupPrefix( namespaceName );
}
// Internal IXmlNamespaceResolver methods
internal IDictionary<string,string> GetNamespacesInScope( XmlNamespaceScope scope ) {
return coreReaderNSResolver.GetNamespacesInScope( scope );
}
internal string LookupPrefix( string namespaceName ) {
return coreReaderNSResolver.LookupPrefix( namespaceName );
}
//
// XmlValidatingReader members
//
// Specufies the validation event handler that wil get warnings and errors related to validation
internal event ValidationEventHandler ValidationEventHandler {
add {
eventHandling.AddHandler(value);
}
remove {
eventHandling.RemoveHandler(value); ;
}
}
// returns the schema type of the current node
internal object SchemaType {
get {
if ( validationType != ValidationType.None ) {
XmlSchemaType schemaTypeObj = coreReaderImpl.InternalSchemaType as XmlSchemaType;
if ( schemaTypeObj != null && schemaTypeObj.QualifiedName.Namespace == XmlReservedNs.NsXs ) {
return schemaTypeObj.Datatype;
}
return coreReaderImpl.InternalSchemaType;
}
else
return null;
}
}
// returns the underlying XmlTextReader or XmlTextReaderImpl
internal XmlReader Reader {
get {
return (XmlReader) coreReader;
}
}
// returns the underlying XmlTextReaderImpl
internal XmlTextReaderImpl ReaderImpl {
get {
return coreReaderImpl;
}
}
// specifies the validation type (None, DDT, XSD, XDR, Auto)
internal ValidationType ValidationType {
get {
return validationType;
}
set {
if ( ReadState != ReadState.Initial ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
validationType = value;
SetupValidation( value );
}
}
// current schema collection used for validationg
#pragma warning disable 618
internal XmlSchemaCollection Schemas {
get {
return schemaCollection;
}
}
#pragma warning restore 618
// Spefifies whether general entities should be automatically expanded or not
internal EntityHandling EntityHandling {
get {
return coreReaderImpl.EntityHandling;
}
set {
coreReaderImpl.EntityHandling = value;
}
}
// Specifies XmlResolver used for opening the XML document and other external references
internal XmlResolver XmlResolver {
set {
coreReaderImpl.XmlResolver = value;
validator.XmlResolver = value;
schemaCollection.XmlResolver = value;
}
}
// Disables or enables support of W3C XML 1.0 Namespaces
internal bool Namespaces {
get {
return coreReaderImpl.Namespaces;
}
set {
coreReaderImpl.Namespaces = value;
}
}
// Returns typed value of the current node (based on the type specified by schema)
public object ReadTypedValue() {
if ( validationType == ValidationType.None ) {
return null;
}
switch ( outerReader.NodeType ) {
case XmlNodeType.Attribute:
return coreReaderImpl.InternalTypedValue;
case XmlNodeType.Element:
if ( SchemaType == null ) {
return null;
}
XmlSchemaDatatype dtype = ( SchemaType is XmlSchemaDatatype ) ? (XmlSchemaDatatype)SchemaType : ((XmlSchemaType)SchemaType).Datatype;
if ( dtype != null ) {
if ( !outerReader.IsEmptyElement ) {
for (;;) {
if ( !outerReader.Read() ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
XmlNodeType type = outerReader.NodeType;
if ( type != XmlNodeType.CDATA && type != XmlNodeType.Text &&
type != XmlNodeType.Whitespace && type != XmlNodeType.SignificantWhitespace &&
type != XmlNodeType.Comment && type != XmlNodeType.ProcessingInstruction ) {
break;
}
}
if ( outerReader.NodeType != XmlNodeType.EndElement ) {
throw new XmlException( Res.Xml_InvalidNodeType, outerReader.NodeType.ToString());
}
}
return coreReaderImpl.InternalTypedValue;
}
return null;
case XmlNodeType.EndElement:
return null;
default:
if ( coreReaderImpl.V1Compat ) { //If v1 XmlValidatingReader return null
return null;
}
else {
return Value;
}
}
}
//
// Private implementation methods
//
private void ParseDtdFromParserContext()
{
Debug.Assert( parserContext != null );
Debug.Assert( coreReaderImpl.DtdInfo == null );
if ( parserContext.DocTypeName == null || parserContext.DocTypeName.Length == 0 ) {
return;
}
IDtdParser dtdParser = DtdParser.Create();
XmlTextReaderImpl.DtdParserProxy proxy = new XmlTextReaderImpl.DtdParserProxy(coreReaderImpl);
IDtdInfo dtdInfo = dtdParser.ParseFreeFloatingDtd( parserContext.BaseURI, parserContext.DocTypeName, parserContext.PublicId,
parserContext.SystemId, parserContext.InternalSubset, proxy );
coreReaderImpl.SetDtdInfo( dtdInfo);
ValidateDtd();
}
private void ValidateDtd() {
IDtdInfo dtdInfo = coreReaderImpl.DtdInfo;
if (dtdInfo != null) {
switch ( validationType ) {
#pragma warning disable 618
case ValidationType.Auto:
SetupValidation( ValidationType.DTD );
goto case ValidationType.DTD;
#pragma warning restore 618
case ValidationType.DTD:
case ValidationType.None:
validator.DtdInfo = dtdInfo;
break;
}
}
}
private void ResolveEntityInternally() {
Debug.Assert( coreReader.NodeType == XmlNodeType.EntityReference );
int initialDepth = coreReader.Depth;
outerReader.ResolveEntity();
while ( outerReader.Read() && coreReader.Depth > initialDepth );
}
// SxS: This method resolves an Uri but does not expose it to caller. It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
private void SetupValidation( ValidationType valType ) {
validator = BaseValidator.CreateInstance( valType, this, schemaCollection, eventHandling , processIdentityConstraints);
XmlResolver resolver = GetResolver();
validator.XmlResolver = resolver;
if ( outerReader.BaseURI.Length > 0 ) {
validator.BaseUri = ( resolver == null ) ? new Uri( outerReader.BaseURI, UriKind.RelativeOrAbsolute ) : resolver.ResolveUri( null, outerReader.BaseURI );
}
coreReaderImpl.ValidationEventHandling = (validationType == ValidationType.None) ? null : eventHandling;
}
static XmlResolver s_tempResolver;
// This is needed because we can't have the setter for XmlResolver public and with internal getter.
private XmlResolver GetResolver() {
XmlResolver tempResolver = coreReaderImpl.GetResolver();
if (tempResolver == null && !coreReaderImpl.IsResolverSet &&
!System.Xml.XmlReaderSettings.EnableLegacyXmlSettings())
{
// it is safe to return valid resolver as it'll be used in the schema validation
if (s_tempResolver == null)
s_tempResolver = new XmlUrlResolver();
return s_tempResolver;
}
return tempResolver;
}
//
// Internal methods for validators, DOM, XPathDocument etc.
//
private void ProcessCoreReaderEvent() {
switch ( coreReader.NodeType ) {
case XmlNodeType.Whitespace:
if ( coreReader.Depth > 0 || coreReaderImpl.FragmentType != XmlNodeType.Document ) {
if ( validator.PreserveWhitespace ) {
coreReaderImpl.ChangeCurrentNodeType( XmlNodeType.SignificantWhitespace );
}
}
goto default;
case XmlNodeType.DocumentType:
ValidateDtd();
break;
case XmlNodeType.EntityReference:
parsingFunction = ParsingFunction.ResolveEntityInternally;
goto default;
default:
coreReaderImpl.InternalSchemaType = null;
coreReaderImpl.InternalTypedValue = null;
validator.Validate();
break;
}
}
internal void Close( bool closeStream ) {
coreReaderImpl.Close( closeStream );
parsingFunction = ParsingFunction.ReaderClosed;
}
internal BaseValidator Validator {
get {
return validator;
}
set {
validator = value;
}
}
internal override XmlNamespaceManager NamespaceManager {
get {
return coreReaderImpl.NamespaceManager;
}
}
internal bool StandAlone {
get {
return coreReaderImpl.StandAlone;
}
}
internal object SchemaTypeObject {
set {
coreReaderImpl.InternalSchemaType = value;
}
}
internal object TypedValueObject {
get {
return coreReaderImpl.InternalTypedValue;
}
set {
coreReaderImpl.InternalTypedValue = value;
}
}
internal bool Normalization {
get {
return coreReaderImpl.Normalization;
}
}
internal bool AddDefaultAttribute( SchemaAttDef attdef ) {
return coreReaderImpl.AddDefaultAttributeNonDtd( attdef );
}
internal override IDtdInfo DtdInfo {
get { return coreReaderImpl.DtdInfo; }
}
internal void ValidateDefaultAttributeOnUse(IDtdDefaultAttributeInfo defaultAttribute, XmlTextReaderImpl coreReader) {
SchemaAttDef attdef = defaultAttribute as SchemaAttDef;
if (attdef == null) {
return;
}
if (!attdef.DefaultValueChecked) {
SchemaInfo schemaInfo = coreReader.DtdInfo as SchemaInfo;
if (schemaInfo == null) {
return;
}
DtdValidator.CheckDefaultValue(attdef, schemaInfo, eventHandling, coreReader.BaseURI);
}
}
}
}
|