Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Xml / System / Xml / Core / XmlSubtreeReader.cs / 1 / XmlSubtreeReader.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Xml; using System.Xml.Schema; using System.Diagnostics; using System.Collections; using System.Globalization; using System.Collections.Generic; namespace System.Xml { internal sealed class XmlSubtreeReader : XmlWrappingReader, IXmlNamespaceResolver { // // Private types // class NodeData { internal XmlNodeType type; internal string localName; internal string prefix; internal string name; internal string namespaceUri; internal string value; internal NodeData() { } internal void Set( XmlNodeType nodeType, string localName, string prefix, string name, string namespaceUri, string value ) { this.type = nodeType; this.localName = localName; this.prefix = prefix; this.name = name; this.namespaceUri = namespaceUri; this.value = value; } } enum State { Initial = ReadState.Initial, Interactive = ReadState.Interactive, Error = ReadState.Error, EndOfFile = ReadState.EndOfFile, Closed = ReadState.Closed, PopNamespaceScope, ClearNsAttributes, ReadElementContentAsBase64, ReadElementContentAsBinHex, ReadContentAsBase64, ReadContentAsBinHex, } const int AttributeActiveStates = 0x62; // 00001100010 bin const int NamespaceActiveStates = 0x7E2; // 11111100010 bin // // Fields // int initialDepth; State state; // namespace management XmlNamespaceManager nsManager; NodeData[] nsAttributes; int nsAttrCount; int curNsAttr = -1; string xmlns; string xmlnsUri; // cached nodes bool useCurNode; NodeData curNode; // node used for a text node of ReadAttributeValue or as Initial or EOF node NodeData tmpNode; // // Constants // internal int InitialNamespaceAttributeCount = 4; // // Constructor // internal XmlSubtreeReader( XmlReader reader ) : base( reader ) { initialDepth = reader.Depth; state = State.Initial; nsManager = new XmlNamespaceManager( reader.NameTable ); xmlns = reader.NameTable.Add( "xmlns" ); xmlnsUri = reader.NameTable.Add(XmlReservedNs.NsXmlNs); tmpNode = new NodeData(); tmpNode.Set( XmlNodeType.None, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty ); SetCurrentNode( tmpNode ); } // // XmlReader implementation // public override XmlReaderSettings Settings { get { return reader.Settings; } } public override XmlNodeType NodeType { get { return ( useCurNode ) ? curNode.type : reader.NodeType; } } public override string Name { get { return ( useCurNode ) ? curNode.name : reader.Name; } } public override string LocalName { get { return ( useCurNode ) ? curNode.localName : reader.LocalName; } } public override string NamespaceURI { get { return ( useCurNode ) ? curNode.namespaceUri : reader.NamespaceURI; } } public override string Prefix { get { return ( useCurNode ) ? curNode.prefix : reader.Prefix; } } public override string Value { get { return ( useCurNode ) ? curNode.value : reader.Value; } } public override int Depth { get { int depth = reader.Depth - initialDepth; if ( curNsAttr != -1 ) { if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value depth += 2; } else { depth++; } } return depth; } } public override string BaseURI { get { return reader.BaseURI; } } public override bool CanResolveEntity { get { return reader.CanResolveEntity; } } public override bool EOF { get { return state == State.EndOfFile || state == State.Closed; } } public override ReadState ReadState { get { if ( reader.ReadState == ReadState.Error ) { return ReadState.Error; } else { if ( (int)state <= (int)State.Closed ) { return (ReadState)(int)state; } else { return ReadState.Interactive; } } } } public override XmlNameTable NameTable { get { return reader.NameTable; } } public override int AttributeCount { get { return InAttributeActiveState ? reader.AttributeCount + nsAttrCount : 0; } } public override string GetAttribute( string name ) { if ( !InAttributeActiveState ) { return null; } string attr = reader.GetAttribute( name ); if ( attr != null ) { return attr; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].name ) { return nsAttributes[i].value; } } return null; } public override string GetAttribute( string name, string namespaceURI ) { if ( !InAttributeActiveState ) { return null; } string attr = reader.GetAttribute( name, namespaceURI ); if ( attr != null ) { return attr; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].localName && namespaceURI == xmlnsUri ) { return nsAttributes[i].value; } } return null; } public override string GetAttribute( int i ) { if ( !InAttributeActiveState ) { throw new ArgumentOutOfRangeException("i"); } int n = reader.AttributeCount; if ( i < n ) { return reader.GetAttribute( i ); } else if ( i - n < nsAttrCount ) { return nsAttributes[i-n].value; } else { throw new ArgumentOutOfRangeException( "i" ); } } public override bool MoveToAttribute( string name ) { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToAttribute( name ) ) { curNsAttr = -1; useCurNode = false; return true; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].name ) { MoveToNsAttribute( i ); return true; } } return false; } public override bool MoveToAttribute( string name, string ns ) { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToAttribute( name, ns ) ) { curNsAttr = -1; useCurNode = false; return true; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].localName && ns == xmlnsUri ) { MoveToNsAttribute( i ); return true; } } return false; } public override void MoveToAttribute( int i ) { if ( !InAttributeActiveState ) { throw new ArgumentOutOfRangeException("i"); } int n = reader.AttributeCount; if ( i < n ) { reader.MoveToAttribute( i ); curNsAttr = -1; useCurNode = false; } else if ( i - n < nsAttrCount ) { MoveToNsAttribute( i - n ); } else { throw new ArgumentOutOfRangeException( "i" ); } } public override bool MoveToFirstAttribute() { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToFirstAttribute() ) { useCurNode = false; return true; } if ( nsAttrCount > 0 ) { MoveToNsAttribute( 0 ); return true; } return false; } public override bool MoveToNextAttribute() { if ( !InAttributeActiveState ) { return false; } if ( curNsAttr == -1 && reader.MoveToNextAttribute() ) { return true; } if ( curNsAttr + 1 < nsAttrCount ) { MoveToNsAttribute( curNsAttr + 1 ); return true; } return false; } public override bool MoveToElement() { if ( !InAttributeActiveState ) { return false; } curNsAttr = -1; useCurNode = false; return reader.MoveToElement(); } public override bool ReadAttributeValue() { if ( !InAttributeActiveState ) { return false; } if ( curNsAttr == -1 ) { return reader.ReadAttributeValue(); } else if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value return false; } else { Debug.Assert( curNode.type == XmlNodeType.Attribute ); tmpNode.type = XmlNodeType.Text; tmpNode.value = curNode.value; SetCurrentNode( tmpNode ); return true; } } public override bool Read() { switch ( state ) { case State.Initial: useCurNode = false; state = State.Interactive; ProcessNamespaces(); return true; case State.Interactive: curNsAttr = -1; useCurNode = false; reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); if ( reader.Depth == initialDepth ) { if ( reader.NodeType == XmlNodeType.EndElement || ( reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ) ) { state = State.EndOfFile; SetEmptyNode(); return false; } Debug.Assert( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ); } if ( reader.Read() ) { ProcessNamespaces(); return true; } else { SetEmptyNode(); return false; } case State.EndOfFile: case State.Closed: return false; case State.PopNamespaceScope: nsManager.PopScope(); goto case State.ClearNsAttributes; case State.ClearNsAttributes: nsAttrCount = 0; state = State.Interactive; goto case State.Interactive; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: if ( !FinishReadElementContentAsBinary() ) { return false; } return Read(); case State.ReadContentAsBase64: case State.ReadContentAsBinHex: if ( !FinishReadContentAsBinary() ) { return false; } return Read(); default: Debug.Assert( false ); return false; } } public override void Close() { if ( state == State.Closed ) { return; } try { // move the underlying reader to the next sibling if ( state != State.EndOfFile ) { reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); // move off the root of the subtree if ( reader.Depth == initialDepth && reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { reader.Read(); } // move to the end of the subtree, do nothing if on empty root element while ( reader.Depth > initialDepth && reader.Read() ) { /* intentionally empty */ } } } catch { // never fail... } finally { curNsAttr = -1; useCurNode = false; state = State.Closed; SetEmptyNode(); } } public override void Skip() { switch ( state ) { case State.Initial: Read(); return; case State.Interactive: curNsAttr = -1; useCurNode = false; reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); if ( reader.Depth == initialDepth ) { if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { // we are on root of the subtree -> skip to the end element and set to Eof state if ( reader.Read() ) { while ( reader.NodeType != XmlNodeType.EndElement && reader.Depth > initialDepth ) { reader.Skip(); } } } Debug.Assert( reader.NodeType == XmlNodeType.EndElement || reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement || reader.ReadState != ReadState.Interactive ); state = State.EndOfFile; SetEmptyNode(); return; } if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { nsManager.PopScope(); } reader.Skip(); ProcessNamespaces(); Debug.Assert( reader.Depth >= initialDepth ); return; case State.Closed: case State.EndOfFile: return; case State.PopNamespaceScope: nsManager.PopScope(); goto case State.ClearNsAttributes; case State.ClearNsAttributes: nsAttrCount = 0; state = State.Interactive; goto case State.Interactive; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: if ( FinishReadElementContentAsBinary() ) { Skip(); } break; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: if ( FinishReadContentAsBinary() ) { Skip(); } break; default: Debug.Assert( false ); return; } } public override object ReadContentAsObject() { try { InitReadContentAsType( "ReadContentAsObject" ); object value = reader.ReadContentAsObject(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override bool ReadContentAsBoolean() { try { InitReadContentAsType( "ReadContentAsBoolean" ); bool value = reader.ReadContentAsBoolean(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override DateTime ReadContentAsDateTime() { try { InitReadContentAsType( "ReadContentAsDateTime" ); DateTime value = reader.ReadContentAsDateTime(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override double ReadContentAsDouble() { try { InitReadContentAsType( "ReadContentAsDouble" ); double value = reader.ReadContentAsDouble(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override float ReadContentAsFloat() { try { InitReadContentAsType( "ReadContentAsFloat" ); float value = reader.ReadContentAsFloat(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override decimal ReadContentAsDecimal() { try { InitReadContentAsType( "ReadContentAsDecimal" ); decimal value = reader.ReadContentAsDecimal(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override int ReadContentAsInt() { try { InitReadContentAsType( "ReadContentAsInt" ); int value = reader.ReadContentAsInt(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override long ReadContentAsLong() { try { InitReadContentAsType( "ReadContentAsLong" ); long value = reader.ReadContentAsLong(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override string ReadContentAsString() { try { InitReadContentAsType( "ReadContentAsString" ); string value = reader.ReadContentAsString(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override object ReadContentAs( Type returnType, IXmlNamespaceResolver namespaceResolver ) { try { InitReadContentAsType( "ReadContentAs" ); object value = reader.ReadContentAs( returnType, namespaceResolver ); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override bool CanReadBinaryContent { get { return reader.CanReadBinaryContent; } } public override int ReadContentAsBase64( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: switch ( NodeType ) { case XmlNodeType.Element: throw CreateReadContentAsException( "ReadContentAsBase64" ); case XmlNodeType.EndElement: return 0; case XmlNodeType.Attribute: case XmlNodeType.Text: Debug.Assert( AttributeCount > 0 ); return reader.ReadContentAsBase64( buffer, index, count ); default: Debug.Assert( false ); return 0; } case State.Interactive: state = State.ReadContentAsBase64; goto case State.ReadContentAsBase64; case State.ReadContentAsBase64: int read = reader.ReadContentAsBase64( buffer, index, count ); if ( read == 0 ) { state = State.Interactive; ProcessNamespaces(); } return read; case State.ReadContentAsBinHex: case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.Interactive: case State.PopNamespaceScope: case State.ClearNsAttributes: if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBase64 ) ) { return 0; } goto case State.ReadElementContentAsBase64; case State.ReadElementContentAsBase64: int read = reader.ReadContentAsBase64( buffer, index, count ); if ( read > 0 ) { return read; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // set eof state or move off the end element if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); } else { Read(); } return 0; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: switch ( NodeType ) { case XmlNodeType.Element: throw CreateReadContentAsException( "ReadContentAsBinHex" ); case XmlNodeType.EndElement: return 0; case XmlNodeType.Attribute: case XmlNodeType.Text: Debug.Assert( AttributeCount > 0 ); return reader.ReadContentAsBinHex( buffer, index, count ); default: Debug.Assert( false ); return 0; } case State.Interactive: state = State.ReadContentAsBinHex; goto case State.ReadContentAsBinHex; case State.ReadContentAsBinHex: int read = reader.ReadContentAsBinHex( buffer, index, count ); if ( read == 0 ) { state = State.Interactive; ProcessNamespaces(); } return read; case State.ReadContentAsBase64: case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.Interactive: case State.PopNamespaceScope: case State.ClearNsAttributes: if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBinHex ) ) { return 0; } goto case State.ReadElementContentAsBinHex; case State.ReadElementContentAsBinHex: int read = reader.ReadContentAsBinHex( buffer, index, count ); if ( read > 0 ) { return read; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // set eof state or move off the end element if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); } else { Read(); } return 0; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: case State.ReadElementContentAsBase64: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override bool CanReadValueChunk { get { return reader.CanReadValueChunk; } } public override int ReadValueChunk( char[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: case State.Error: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: // no need to clean ns attributes or pop scope because the reader when ReadValueChunk is called // - on Element errors // - on EndElement errors // - on Attribute does not move // and that's all where State.ClearNsAttributes or State.PopnamespaceScope can be set goto case State.Interactive; case State.Interactive: return reader.ReadValueChunk( buffer, index, count ); case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: case State.ReadContentAsBase64: case State.ReadContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); default: Debug.Assert( false ); return 0; } } // // IDisposable interface // protected override void Dispose( bool disposing ) { // note: we do not want to dispose the underlying reader this.Close(); } // // IXmlLineInfo members // public override int LineNumber { get { return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LineNumber; } } public override int LinePosition { get { return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LinePosition; } } public override string LookupNamespace( string prefix ) { return ((IXmlNamespaceResolver)this).LookupNamespace( prefix ); } // // IXmlNamespaceResolver implementation // IDictionaryIXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { if ( !InNamespaceActiveState ) { return new Dictionary (); } return nsManager.GetNamespacesInScope( scope ); } string IXmlNamespaceResolver.LookupNamespace( string prefix ) { if ( !InNamespaceActiveState ) { return null; } return nsManager.LookupNamespace( prefix ); } string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) { if ( !InNamespaceActiveState ) { return null; } return nsManager.LookupPrefix( namespaceName ); } // // Internal methods // internal override SchemaInfo DtdSchemaInfo { get { return null; } } // // Private methods // private void ProcessNamespaces() { switch ( reader.NodeType ) { case XmlNodeType.Element: nsManager.PushScope(); string prefix = reader.Prefix; string ns = reader.NamespaceURI; if ( nsManager.LookupNamespace( prefix ) != ns ) { AddNamespace( prefix, ns ); } if ( reader.MoveToFirstAttribute() ) { do { prefix = reader.Prefix; ns = reader.NamespaceURI; if ( Ref.Equal( ns, xmlnsUri ) ) { if ( prefix.Length == 0 ) { nsManager.AddNamespace( string.Empty, reader.Value ); RemoveNamespace( string.Empty, xmlns ); } else { prefix = reader.LocalName; nsManager.AddNamespace( prefix, reader.Value ); RemoveNamespace( xmlns, prefix ); } } else if ( prefix.Length != 0 && nsManager.LookupNamespace( prefix ) != ns ) { AddNamespace( prefix, ns ); } } while ( reader.MoveToNextAttribute() ); reader.MoveToElement(); } if ( reader.IsEmptyElement ) { state = State.PopNamespaceScope; } break; case XmlNodeType.EndElement: state = State.PopNamespaceScope; break; } } private void AddNamespace( string prefix, string ns ) { nsManager.AddNamespace( prefix, ns ); int index = nsAttrCount++; if ( nsAttributes == null ) { nsAttributes = new NodeData[InitialNamespaceAttributeCount]; } if ( index == nsAttributes.Length ) { NodeData[] newNsAttrs = new NodeData[nsAttributes.Length * 2]; Array.Copy( nsAttributes, 0, newNsAttrs, 0, index ); nsAttributes = newNsAttrs; } if ( nsAttributes[index] == null ) { nsAttributes[index] = new NodeData(); } if ( prefix.Length == 0 ) { nsAttributes[index].Set( XmlNodeType.Attribute, xmlns, string.Empty, xmlns, XmlReservedNs.NsXmlNs, ns ); } else { nsAttributes[index].Set( XmlNodeType.Attribute, prefix, xmlns, string.Concat( xmlns, ":", prefix ), XmlReservedNs.NsXmlNs, ns ); } Debug.Assert( state == State.ClearNsAttributes || state == State.Interactive || state == State.PopNamespaceScope ); state = State.ClearNsAttributes; curNsAttr = -1; } private void RemoveNamespace( string prefix, string localName ) { for ( int i = 0; i < nsAttrCount; i++ ) { if ( Ref.Equal( prefix, nsAttributes[i].prefix ) && Ref.Equal( localName, nsAttributes[i].localName ) ) { if ( i < nsAttrCount - 1 ) { // swap NodeData tmpNodeData = nsAttributes[i]; nsAttributes[i] = nsAttributes[nsAttrCount - 1]; nsAttributes[nsAttrCount - 1] = tmpNodeData; } nsAttrCount--; break; } } } private void MoveToNsAttribute( int index ) { Debug.Assert( index >= 0 && index <= nsAttrCount ); reader.MoveToElement(); curNsAttr = index; SetCurrentNode( nsAttributes[index] ); } private bool InitReadElementContentAsBinary( State binaryState ) { if ( NodeType != XmlNodeType.Element ) { throw reader.CreateReadElementContentAsException( "ReadElementContentAsBase64" ); } bool isEmpty = IsEmptyElement; // move to content or off the empty element if ( !Read() || isEmpty ) { return false; } // special-case child element and end element switch ( NodeType ) { case XmlNodeType.Element: throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); case XmlNodeType.EndElement: // pop scope & move off end element ProcessNamespaces(); Read(); return false; } Debug.Assert( state == State.Interactive ); state = binaryState; return true; } private bool FinishReadElementContentAsBinary() { Debug.Assert( state == State.ReadElementContentAsBase64 || state == State.ReadElementContentAsBinHex ); byte[] bytes = new byte[256]; if ( state == State.ReadElementContentAsBase64 ) { while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; } else { while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // check eof if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); return false; } // move off end element return Read(); } private bool FinishReadContentAsBinary() { Debug.Assert( state == State.ReadContentAsBase64 || state == State.ReadContentAsBinHex ); byte[] bytes = new byte[256]; if ( state == State.ReadContentAsBase64 ) { while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; } else { while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; } state = State.Interactive; ProcessNamespaces(); // check eof if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); return false; } return true; } private bool InAttributeActiveState { get { #if DEBUG Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Initial ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.Interactive ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Error ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.EndOfFile ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Closed ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); #endif return 0 != ( AttributeActiveStates & ( 1 << (int)state ) ); } } private bool InNamespaceActiveState { get { #if DEBUG Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Initial ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.Interactive ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Error ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.EndOfFile ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Closed ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); #endif return 0 != ( NamespaceActiveStates & ( 1 << (int)state ) ); } } void SetEmptyNode() { Debug.Assert( tmpNode.localName == string.Empty && tmpNode.prefix == string.Empty && tmpNode.name == string.Empty && tmpNode.namespaceUri == string.Empty ); tmpNode.type = XmlNodeType.None; tmpNode.value = string.Empty; curNode = tmpNode; useCurNode = true; } void SetCurrentNode( NodeData node ) { curNode = node; useCurNode = true; } void InitReadContentAsType( string methodName ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: case State.Error: break; case State.Interactive: return; case State.PopNamespaceScope: case State.ClearNsAttributes: // no need to clean ns attributes or pop scope because the reader when ReadContentAs is called // - on Element errors // - on Attribute does not move // - on EndElement does not move // and that's all where State.ClearNsAttributes or State.PopNamespacScope can be set return; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: case State.ReadContentAsBase64: case State.ReadContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); default: Debug.Assert( false ); break; } throw CreateReadContentAsException( methodName ); } void FinishReadContentAsType() { Debug.Assert( state == State.Interactive || state == State.PopNamespaceScope || state == State.ClearNsAttributes ); switch ( NodeType ) { case XmlNodeType.Element: // new element we moved to - process namespaces ProcessNamespaces(); break; case XmlNodeType.EndElement: // end element we've stayed on or have been moved to state = State.PopNamespaceScope; break; case XmlNodeType.Attribute: // stayed on attribute, do nothing break; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Xml; using System.Xml.Schema; using System.Diagnostics; using System.Collections; using System.Globalization; using System.Collections.Generic; namespace System.Xml { internal sealed class XmlSubtreeReader : XmlWrappingReader, IXmlNamespaceResolver { // // Private types // class NodeData { internal XmlNodeType type; internal string localName; internal string prefix; internal string name; internal string namespaceUri; internal string value; internal NodeData() { } internal void Set( XmlNodeType nodeType, string localName, string prefix, string name, string namespaceUri, string value ) { this.type = nodeType; this.localName = localName; this.prefix = prefix; this.name = name; this.namespaceUri = namespaceUri; this.value = value; } } enum State { Initial = ReadState.Initial, Interactive = ReadState.Interactive, Error = ReadState.Error, EndOfFile = ReadState.EndOfFile, Closed = ReadState.Closed, PopNamespaceScope, ClearNsAttributes, ReadElementContentAsBase64, ReadElementContentAsBinHex, ReadContentAsBase64, ReadContentAsBinHex, } const int AttributeActiveStates = 0x62; // 00001100010 bin const int NamespaceActiveStates = 0x7E2; // 11111100010 bin // // Fields // int initialDepth; State state; // namespace management XmlNamespaceManager nsManager; NodeData[] nsAttributes; int nsAttrCount; int curNsAttr = -1; string xmlns; string xmlnsUri; // cached nodes bool useCurNode; NodeData curNode; // node used for a text node of ReadAttributeValue or as Initial or EOF node NodeData tmpNode; // // Constants // internal int InitialNamespaceAttributeCount = 4; // // Constructor // internal XmlSubtreeReader( XmlReader reader ) : base( reader ) { initialDepth = reader.Depth; state = State.Initial; nsManager = new XmlNamespaceManager( reader.NameTable ); xmlns = reader.NameTable.Add( "xmlns" ); xmlnsUri = reader.NameTable.Add(XmlReservedNs.NsXmlNs); tmpNode = new NodeData(); tmpNode.Set( XmlNodeType.None, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty ); SetCurrentNode( tmpNode ); } // // XmlReader implementation // public override XmlReaderSettings Settings { get { return reader.Settings; } } public override XmlNodeType NodeType { get { return ( useCurNode ) ? curNode.type : reader.NodeType; } } public override string Name { get { return ( useCurNode ) ? curNode.name : reader.Name; } } public override string LocalName { get { return ( useCurNode ) ? curNode.localName : reader.LocalName; } } public override string NamespaceURI { get { return ( useCurNode ) ? curNode.namespaceUri : reader.NamespaceURI; } } public override string Prefix { get { return ( useCurNode ) ? curNode.prefix : reader.Prefix; } } public override string Value { get { return ( useCurNode ) ? curNode.value : reader.Value; } } public override int Depth { get { int depth = reader.Depth - initialDepth; if ( curNsAttr != -1 ) { if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value depth += 2; } else { depth++; } } return depth; } } public override string BaseURI { get { return reader.BaseURI; } } public override bool CanResolveEntity { get { return reader.CanResolveEntity; } } public override bool EOF { get { return state == State.EndOfFile || state == State.Closed; } } public override ReadState ReadState { get { if ( reader.ReadState == ReadState.Error ) { return ReadState.Error; } else { if ( (int)state <= (int)State.Closed ) { return (ReadState)(int)state; } else { return ReadState.Interactive; } } } } public override XmlNameTable NameTable { get { return reader.NameTable; } } public override int AttributeCount { get { return InAttributeActiveState ? reader.AttributeCount + nsAttrCount : 0; } } public override string GetAttribute( string name ) { if ( !InAttributeActiveState ) { return null; } string attr = reader.GetAttribute( name ); if ( attr != null ) { return attr; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].name ) { return nsAttributes[i].value; } } return null; } public override string GetAttribute( string name, string namespaceURI ) { if ( !InAttributeActiveState ) { return null; } string attr = reader.GetAttribute( name, namespaceURI ); if ( attr != null ) { return attr; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].localName && namespaceURI == xmlnsUri ) { return nsAttributes[i].value; } } return null; } public override string GetAttribute( int i ) { if ( !InAttributeActiveState ) { throw new ArgumentOutOfRangeException("i"); } int n = reader.AttributeCount; if ( i < n ) { return reader.GetAttribute( i ); } else if ( i - n < nsAttrCount ) { return nsAttributes[i-n].value; } else { throw new ArgumentOutOfRangeException( "i" ); } } public override bool MoveToAttribute( string name ) { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToAttribute( name ) ) { curNsAttr = -1; useCurNode = false; return true; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].name ) { MoveToNsAttribute( i ); return true; } } return false; } public override bool MoveToAttribute( string name, string ns ) { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToAttribute( name, ns ) ) { curNsAttr = -1; useCurNode = false; return true; } for ( int i = 0; i < nsAttrCount; i++ ) { if ( name == nsAttributes[i].localName && ns == xmlnsUri ) { MoveToNsAttribute( i ); return true; } } return false; } public override void MoveToAttribute( int i ) { if ( !InAttributeActiveState ) { throw new ArgumentOutOfRangeException("i"); } int n = reader.AttributeCount; if ( i < n ) { reader.MoveToAttribute( i ); curNsAttr = -1; useCurNode = false; } else if ( i - n < nsAttrCount ) { MoveToNsAttribute( i - n ); } else { throw new ArgumentOutOfRangeException( "i" ); } } public override bool MoveToFirstAttribute() { if ( !InAttributeActiveState ) { return false; } if ( reader.MoveToFirstAttribute() ) { useCurNode = false; return true; } if ( nsAttrCount > 0 ) { MoveToNsAttribute( 0 ); return true; } return false; } public override bool MoveToNextAttribute() { if ( !InAttributeActiveState ) { return false; } if ( curNsAttr == -1 && reader.MoveToNextAttribute() ) { return true; } if ( curNsAttr + 1 < nsAttrCount ) { MoveToNsAttribute( curNsAttr + 1 ); return true; } return false; } public override bool MoveToElement() { if ( !InAttributeActiveState ) { return false; } curNsAttr = -1; useCurNode = false; return reader.MoveToElement(); } public override bool ReadAttributeValue() { if ( !InAttributeActiveState ) { return false; } if ( curNsAttr == -1 ) { return reader.ReadAttributeValue(); } else if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value return false; } else { Debug.Assert( curNode.type == XmlNodeType.Attribute ); tmpNode.type = XmlNodeType.Text; tmpNode.value = curNode.value; SetCurrentNode( tmpNode ); return true; } } public override bool Read() { switch ( state ) { case State.Initial: useCurNode = false; state = State.Interactive; ProcessNamespaces(); return true; case State.Interactive: curNsAttr = -1; useCurNode = false; reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); if ( reader.Depth == initialDepth ) { if ( reader.NodeType == XmlNodeType.EndElement || ( reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ) ) { state = State.EndOfFile; SetEmptyNode(); return false; } Debug.Assert( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ); } if ( reader.Read() ) { ProcessNamespaces(); return true; } else { SetEmptyNode(); return false; } case State.EndOfFile: case State.Closed: return false; case State.PopNamespaceScope: nsManager.PopScope(); goto case State.ClearNsAttributes; case State.ClearNsAttributes: nsAttrCount = 0; state = State.Interactive; goto case State.Interactive; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: if ( !FinishReadElementContentAsBinary() ) { return false; } return Read(); case State.ReadContentAsBase64: case State.ReadContentAsBinHex: if ( !FinishReadContentAsBinary() ) { return false; } return Read(); default: Debug.Assert( false ); return false; } } public override void Close() { if ( state == State.Closed ) { return; } try { // move the underlying reader to the next sibling if ( state != State.EndOfFile ) { reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); // move off the root of the subtree if ( reader.Depth == initialDepth && reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { reader.Read(); } // move to the end of the subtree, do nothing if on empty root element while ( reader.Depth > initialDepth && reader.Read() ) { /* intentionally empty */ } } } catch { // never fail... } finally { curNsAttr = -1; useCurNode = false; state = State.Closed; SetEmptyNode(); } } public override void Skip() { switch ( state ) { case State.Initial: Read(); return; case State.Interactive: curNsAttr = -1; useCurNode = false; reader.MoveToElement(); Debug.Assert( reader.Depth >= initialDepth ); if ( reader.Depth == initialDepth ) { if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { // we are on root of the subtree -> skip to the end element and set to Eof state if ( reader.Read() ) { while ( reader.NodeType != XmlNodeType.EndElement && reader.Depth > initialDepth ) { reader.Skip(); } } } Debug.Assert( reader.NodeType == XmlNodeType.EndElement || reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement || reader.ReadState != ReadState.Interactive ); state = State.EndOfFile; SetEmptyNode(); return; } if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { nsManager.PopScope(); } reader.Skip(); ProcessNamespaces(); Debug.Assert( reader.Depth >= initialDepth ); return; case State.Closed: case State.EndOfFile: return; case State.PopNamespaceScope: nsManager.PopScope(); goto case State.ClearNsAttributes; case State.ClearNsAttributes: nsAttrCount = 0; state = State.Interactive; goto case State.Interactive; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: if ( FinishReadElementContentAsBinary() ) { Skip(); } break; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: if ( FinishReadContentAsBinary() ) { Skip(); } break; default: Debug.Assert( false ); return; } } public override object ReadContentAsObject() { try { InitReadContentAsType( "ReadContentAsObject" ); object value = reader.ReadContentAsObject(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override bool ReadContentAsBoolean() { try { InitReadContentAsType( "ReadContentAsBoolean" ); bool value = reader.ReadContentAsBoolean(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override DateTime ReadContentAsDateTime() { try { InitReadContentAsType( "ReadContentAsDateTime" ); DateTime value = reader.ReadContentAsDateTime(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override double ReadContentAsDouble() { try { InitReadContentAsType( "ReadContentAsDouble" ); double value = reader.ReadContentAsDouble(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override float ReadContentAsFloat() { try { InitReadContentAsType( "ReadContentAsFloat" ); float value = reader.ReadContentAsFloat(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override decimal ReadContentAsDecimal() { try { InitReadContentAsType( "ReadContentAsDecimal" ); decimal value = reader.ReadContentAsDecimal(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override int ReadContentAsInt() { try { InitReadContentAsType( "ReadContentAsInt" ); int value = reader.ReadContentAsInt(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override long ReadContentAsLong() { try { InitReadContentAsType( "ReadContentAsLong" ); long value = reader.ReadContentAsLong(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override string ReadContentAsString() { try { InitReadContentAsType( "ReadContentAsString" ); string value = reader.ReadContentAsString(); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override object ReadContentAs( Type returnType, IXmlNamespaceResolver namespaceResolver ) { try { InitReadContentAsType( "ReadContentAs" ); object value = reader.ReadContentAs( returnType, namespaceResolver ); FinishReadContentAsType(); return value; } catch { state = State.Error; throw; } } public override bool CanReadBinaryContent { get { return reader.CanReadBinaryContent; } } public override int ReadContentAsBase64( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: switch ( NodeType ) { case XmlNodeType.Element: throw CreateReadContentAsException( "ReadContentAsBase64" ); case XmlNodeType.EndElement: return 0; case XmlNodeType.Attribute: case XmlNodeType.Text: Debug.Assert( AttributeCount > 0 ); return reader.ReadContentAsBase64( buffer, index, count ); default: Debug.Assert( false ); return 0; } case State.Interactive: state = State.ReadContentAsBase64; goto case State.ReadContentAsBase64; case State.ReadContentAsBase64: int read = reader.ReadContentAsBase64( buffer, index, count ); if ( read == 0 ) { state = State.Interactive; ProcessNamespaces(); } return read; case State.ReadContentAsBinHex: case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.Interactive: case State.PopNamespaceScope: case State.ClearNsAttributes: if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBase64 ) ) { return 0; } goto case State.ReadElementContentAsBase64; case State.ReadElementContentAsBase64: int read = reader.ReadContentAsBase64( buffer, index, count ); if ( read > 0 ) { return read; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // set eof state or move off the end element if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); } else { Read(); } return 0; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: switch ( NodeType ) { case XmlNodeType.Element: throw CreateReadContentAsException( "ReadContentAsBinHex" ); case XmlNodeType.EndElement: return 0; case XmlNodeType.Attribute: case XmlNodeType.Text: Debug.Assert( AttributeCount > 0 ); return reader.ReadContentAsBinHex( buffer, index, count ); default: Debug.Assert( false ); return 0; } case State.Interactive: state = State.ReadContentAsBinHex; goto case State.ReadContentAsBinHex; case State.ReadContentAsBinHex: int read = reader.ReadContentAsBinHex( buffer, index, count ); if ( read == 0 ) { state = State.Interactive; ProcessNamespaces(); } return read; case State.ReadContentAsBase64: case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: return 0; case State.Interactive: case State.PopNamespaceScope: case State.ClearNsAttributes: if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBinHex ) ) { return 0; } goto case State.ReadElementContentAsBinHex; case State.ReadElementContentAsBinHex: int read = reader.ReadContentAsBinHex( buffer, index, count ); if ( read > 0 ) { return read; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // set eof state or move off the end element if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); } else { Read(); } return 0; case State.ReadContentAsBase64: case State.ReadContentAsBinHex: case State.ReadElementContentAsBase64: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); default: Debug.Assert( false ); return 0; } } public override bool CanReadValueChunk { get { return reader.CanReadValueChunk; } } public override int ReadValueChunk( char[] buffer, int index, int count ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: case State.Error: return 0; case State.ClearNsAttributes: case State.PopNamespaceScope: // no need to clean ns attributes or pop scope because the reader when ReadValueChunk is called // - on Element errors // - on EndElement errors // - on Attribute does not move // and that's all where State.ClearNsAttributes or State.PopnamespaceScope can be set goto case State.Interactive; case State.Interactive: return reader.ReadValueChunk( buffer, index, count ); case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: case State.ReadContentAsBase64: case State.ReadContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); default: Debug.Assert( false ); return 0; } } // // IDisposable interface // protected override void Dispose( bool disposing ) { // note: we do not want to dispose the underlying reader this.Close(); } // // IXmlLineInfo members // public override int LineNumber { get { return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LineNumber; } } public override int LinePosition { get { return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LinePosition; } } public override string LookupNamespace( string prefix ) { return ((IXmlNamespaceResolver)this).LookupNamespace( prefix ); } // // IXmlNamespaceResolver implementation // IDictionaryIXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { if ( !InNamespaceActiveState ) { return new Dictionary (); } return nsManager.GetNamespacesInScope( scope ); } string IXmlNamespaceResolver.LookupNamespace( string prefix ) { if ( !InNamespaceActiveState ) { return null; } return nsManager.LookupNamespace( prefix ); } string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) { if ( !InNamespaceActiveState ) { return null; } return nsManager.LookupPrefix( namespaceName ); } // // Internal methods // internal override SchemaInfo DtdSchemaInfo { get { return null; } } // // Private methods // private void ProcessNamespaces() { switch ( reader.NodeType ) { case XmlNodeType.Element: nsManager.PushScope(); string prefix = reader.Prefix; string ns = reader.NamespaceURI; if ( nsManager.LookupNamespace( prefix ) != ns ) { AddNamespace( prefix, ns ); } if ( reader.MoveToFirstAttribute() ) { do { prefix = reader.Prefix; ns = reader.NamespaceURI; if ( Ref.Equal( ns, xmlnsUri ) ) { if ( prefix.Length == 0 ) { nsManager.AddNamespace( string.Empty, reader.Value ); RemoveNamespace( string.Empty, xmlns ); } else { prefix = reader.LocalName; nsManager.AddNamespace( prefix, reader.Value ); RemoveNamespace( xmlns, prefix ); } } else if ( prefix.Length != 0 && nsManager.LookupNamespace( prefix ) != ns ) { AddNamespace( prefix, ns ); } } while ( reader.MoveToNextAttribute() ); reader.MoveToElement(); } if ( reader.IsEmptyElement ) { state = State.PopNamespaceScope; } break; case XmlNodeType.EndElement: state = State.PopNamespaceScope; break; } } private void AddNamespace( string prefix, string ns ) { nsManager.AddNamespace( prefix, ns ); int index = nsAttrCount++; if ( nsAttributes == null ) { nsAttributes = new NodeData[InitialNamespaceAttributeCount]; } if ( index == nsAttributes.Length ) { NodeData[] newNsAttrs = new NodeData[nsAttributes.Length * 2]; Array.Copy( nsAttributes, 0, newNsAttrs, 0, index ); nsAttributes = newNsAttrs; } if ( nsAttributes[index] == null ) { nsAttributes[index] = new NodeData(); } if ( prefix.Length == 0 ) { nsAttributes[index].Set( XmlNodeType.Attribute, xmlns, string.Empty, xmlns, XmlReservedNs.NsXmlNs, ns ); } else { nsAttributes[index].Set( XmlNodeType.Attribute, prefix, xmlns, string.Concat( xmlns, ":", prefix ), XmlReservedNs.NsXmlNs, ns ); } Debug.Assert( state == State.ClearNsAttributes || state == State.Interactive || state == State.PopNamespaceScope ); state = State.ClearNsAttributes; curNsAttr = -1; } private void RemoveNamespace( string prefix, string localName ) { for ( int i = 0; i < nsAttrCount; i++ ) { if ( Ref.Equal( prefix, nsAttributes[i].prefix ) && Ref.Equal( localName, nsAttributes[i].localName ) ) { if ( i < nsAttrCount - 1 ) { // swap NodeData tmpNodeData = nsAttributes[i]; nsAttributes[i] = nsAttributes[nsAttrCount - 1]; nsAttributes[nsAttrCount - 1] = tmpNodeData; } nsAttrCount--; break; } } } private void MoveToNsAttribute( int index ) { Debug.Assert( index >= 0 && index <= nsAttrCount ); reader.MoveToElement(); curNsAttr = index; SetCurrentNode( nsAttributes[index] ); } private bool InitReadElementContentAsBinary( State binaryState ) { if ( NodeType != XmlNodeType.Element ) { throw reader.CreateReadElementContentAsException( "ReadElementContentAsBase64" ); } bool isEmpty = IsEmptyElement; // move to content or off the empty element if ( !Read() || isEmpty ) { return false; } // special-case child element and end element switch ( NodeType ) { case XmlNodeType.Element: throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); case XmlNodeType.EndElement: // pop scope & move off end element ProcessNamespaces(); Read(); return false; } Debug.Assert( state == State.Interactive ); state = binaryState; return true; } private bool FinishReadElementContentAsBinary() { Debug.Assert( state == State.ReadElementContentAsBase64 || state == State.ReadElementContentAsBinHex ); byte[] bytes = new byte[256]; if ( state == State.ReadElementContentAsBase64 ) { while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; } else { while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; } if ( NodeType != XmlNodeType.EndElement ) { throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); } // pop namespace scope state = State.Interactive; ProcessNamespaces(); // check eof if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); return false; } // move off end element return Read(); } private bool FinishReadContentAsBinary() { Debug.Assert( state == State.ReadContentAsBase64 || state == State.ReadContentAsBinHex ); byte[] bytes = new byte[256]; if ( state == State.ReadContentAsBase64 ) { while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; } else { while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; } state = State.Interactive; ProcessNamespaces(); // check eof if ( reader.Depth == initialDepth ) { state = State.EndOfFile; SetEmptyNode(); return false; } return true; } private bool InAttributeActiveState { get { #if DEBUG Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Initial ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.Interactive ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Error ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.EndOfFile ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Closed ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) ); Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); #endif return 0 != ( AttributeActiveStates & ( 1 << (int)state ) ); } } private bool InNamespaceActiveState { get { #if DEBUG Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Initial ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.Interactive ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Error ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.EndOfFile ) ) ); Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Closed ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) ); Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); #endif return 0 != ( NamespaceActiveStates & ( 1 << (int)state ) ); } } void SetEmptyNode() { Debug.Assert( tmpNode.localName == string.Empty && tmpNode.prefix == string.Empty && tmpNode.name == string.Empty && tmpNode.namespaceUri == string.Empty ); tmpNode.type = XmlNodeType.None; tmpNode.value = string.Empty; curNode = tmpNode; useCurNode = true; } void SetCurrentNode( NodeData node ) { curNode = node; useCurNode = true; } void InitReadContentAsType( string methodName ) { switch ( state ) { case State.Initial: case State.EndOfFile: case State.Closed: case State.Error: break; case State.Interactive: return; case State.PopNamespaceScope: case State.ClearNsAttributes: // no need to clean ns attributes or pop scope because the reader when ReadContentAs is called // - on Element errors // - on Attribute does not move // - on EndElement does not move // and that's all where State.ClearNsAttributes or State.PopNamespacScope can be set return; case State.ReadElementContentAsBase64: case State.ReadElementContentAsBinHex: case State.ReadContentAsBase64: case State.ReadContentAsBinHex: throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); default: Debug.Assert( false ); break; } throw CreateReadContentAsException( methodName ); } void FinishReadContentAsType() { Debug.Assert( state == State.Interactive || state == State.PopNamespaceScope || state == State.ClearNsAttributes ); switch ( NodeType ) { case XmlNodeType.Element: // new element we moved to - process namespaces ProcessNamespaces(); break; case XmlNodeType.EndElement: // end element we've stayed on or have been moved to state = State.PopNamespaceScope; break; case XmlNodeType.Attribute: // stayed on attribute, do nothing break; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StrongName.cs
- MexNamedPipeBindingCollectionElement.cs
- LostFocusEventManager.cs
- StateFinalizationDesigner.cs
- AspNetHostingPermission.cs
- WSHttpBindingBaseElement.cs
- SignalGate.cs
- CategoryNameCollection.cs
- PropertyGeneratedEventArgs.cs
- SamlConstants.cs
- DES.cs
- Triangle.cs
- AppDomain.cs
- Label.cs
- ObjectResult.cs
- CharEntityEncoderFallback.cs
- COM2AboutBoxPropertyDescriptor.cs
- HostedBindingBehavior.cs
- InputLangChangeEvent.cs
- DataBindEngine.cs
- CharStorage.cs
- DocumentPageHost.cs
- HiddenField.cs
- MenuItemAutomationPeer.cs
- GridViewHeaderRowPresenter.cs
- MessageDecoder.cs
- ToolStripDropDownClosedEventArgs.cs
- ImageField.cs
- ToolBar.cs
- EntityClientCacheKey.cs
- FreezableCollection.cs
- DataRowChangeEvent.cs
- TrustManagerPromptUI.cs
- ShaderEffect.cs
- FactoryId.cs
- SecurityKeyType.cs
- ConstNode.cs
- QuadTree.cs
- DataGridViewCellConverter.cs
- FilterQuery.cs
- AsyncResult.cs
- LookupBindingPropertiesAttribute.cs
- SqlProfileProvider.cs
- WebPartsPersonalizationAuthorization.cs
- XPathNodePointer.cs
- fixedPageContentExtractor.cs
- SerializationEventsCache.cs
- _Rfc2616CacheValidators.cs
- RadioButtonAutomationPeer.cs
- DynamicFilterExpression.cs
- EntryPointNotFoundException.cs
- ListViewInsertionMark.cs
- FtpWebRequest.cs
- DbProviderConfigurationHandler.cs
- SqlDependencyListener.cs
- HMAC.cs
- SessionEndingCancelEventArgs.cs
- EdgeProfileValidation.cs
- TileModeValidation.cs
- HelpProvider.cs
- WsatConfiguration.cs
- ToolboxComponentsCreatedEventArgs.cs
- SqlClientMetaDataCollectionNames.cs
- TrustLevel.cs
- CaseInsensitiveComparer.cs
- RtfNavigator.cs
- CqlWriter.cs
- AsymmetricSecurityProtocolFactory.cs
- ToolStripSplitButton.cs
- FocusChangedEventArgs.cs
- InvocationExpression.cs
- PropertyGridEditorPart.cs
- PriorityBinding.cs
- ClockGroup.cs
- CrossAppDomainChannel.cs
- CultureInfo.cs
- SmiXetterAccessMap.cs
- TextSelectionHighlightLayer.cs
- CssClassPropertyAttribute.cs
- SecurityKeyIdentifier.cs
- DebugTraceHelper.cs
- HashSet.cs
- ReadOnlyNameValueCollection.cs
- TypedDataSetSchemaImporterExtension.cs
- DbConnectionPool.cs
- XmlQuerySequence.cs
- _NegoState.cs
- Error.cs
- CustomLineCap.cs
- ConstraintStruct.cs
- AssertFilter.cs
- NetCodeGroup.cs
- RealizationDrawingContextWalker.cs
- EntitySqlQueryCacheKey.cs
- GACMembershipCondition.cs
- BitmapEffectvisualstate.cs
- ElementMarkupObject.cs
- EditorResources.cs
- StorageEntitySetMapping.cs
- ContainsRowNumberChecker.cs