Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / 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
- ItemCollection.cs
- GeneralTransform2DTo3D.cs
- DiagnosticsConfiguration.cs
- SqlDataSource.cs
- UIElementHelper.cs
- ProgressBarRenderer.cs
- UIElementParagraph.cs
- TokenBasedSetEnumerator.cs
- compensatingcollection.cs
- NavigationProperty.cs
- RadialGradientBrush.cs
- PointLightBase.cs
- FixedTextContainer.cs
- ThicknessAnimationBase.cs
- PlainXmlWriter.cs
- WindowsUpDown.cs
- FilterUserControlBase.cs
- X509Chain.cs
- PropertyGridEditorPart.cs
- TriggerAction.cs
- SafeBitVector32.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- Convert.cs
- PageHandlerFactory.cs
- Pair.cs
- DesignTimeTemplateParser.cs
- TextLineBreak.cs
- TogglePatternIdentifiers.cs
- XPathNodeHelper.cs
- OpenTypeLayoutCache.cs
- DesignParameter.cs
- AffineTransform3D.cs
- VisualStyleTypesAndProperties.cs
- DocobjHost.cs
- CollectionType.cs
- CacheDependency.cs
- EmbossBitmapEffect.cs
- PageAdapter.cs
- DefaultAsyncDataDispatcher.cs
- ClientConfigurationHost.cs
- MenuItem.cs
- MethodInfo.cs
- UIElement.cs
- Attributes.cs
- Compiler.cs
- ServiceProviders.cs
- TimelineGroup.cs
- StringSource.cs
- IntegrationExceptionEventArgs.cs
- DbConnectionClosed.cs
- ActivityBindForm.Designer.cs
- DictionaryGlobals.cs
- Resources.Designer.cs
- SimpleNameService.cs
- ColorConverter.cs
- WsdlInspector.cs
- ExpandCollapsePattern.cs
- UniqueConstraint.cs
- _Events.cs
- AccessDataSourceWizardForm.cs
- Transaction.cs
- CapabilitiesAssignment.cs
- EqualityComparer.cs
- DataViewManager.cs
- SecurityTokenResolver.cs
- ItemsPresenter.cs
- COAUTHIDENTITY.cs
- ConsumerConnectionPointCollection.cs
- ContourSegment.cs
- DesignerProperties.cs
- DeploymentSection.cs
- GlobalEventManager.cs
- WebPartManagerInternals.cs
- CorrelationValidator.cs
- WindowsTooltip.cs
- CodeTypeDelegate.cs
- DecimalConverter.cs
- srgsitem.cs
- CustomAttributeFormatException.cs
- SchemaElement.cs
- Monitor.cs
- XmlObjectSerializerWriteContextComplexJson.cs
- WebPartExportVerb.cs
- Int32Animation.cs
- MimeFormatExtensions.cs
- PropertyDescriptorCollection.cs
- EventToken.cs
- DecoratedNameAttribute.cs
- InheritablePropertyChangeInfo.cs
- NodeFunctions.cs
- PolyLineSegmentFigureLogic.cs
- UIHelper.cs
- SqlRowUpdatedEvent.cs
- TimeSpanSecondsConverter.cs
- HttpFileCollection.cs
- UniqueID.cs
- MessageQueueException.cs
- OleDbCommandBuilder.cs
- ZipArchive.cs
- XmlSchemaParticle.cs