// // System.Xml.XmlNodeReader2.cs - splitted XmlNodeReader that manages entities. // // Author: // Duncan Mak (duncan@ximian.com) // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp) // // (C) Ximian, Inc. // (C) Atsushi Enomoto // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; #if NET_2_0 using System.Collections.Generic; #endif using System.Xml; using System.Xml.Schema; using System.Text; using Mono.Xml; namespace System.Xml { #if NET_2_0 public class XmlNodeReader : XmlReader, IHasXmlParserContext, IXmlNamespaceResolver #else public class XmlNodeReader : XmlReader, IHasXmlParserContext #endif { XmlReader entity; XmlNodeReaderImpl source; bool entityInsideAttribute; bool insideAttribute; #region Constructor public XmlNodeReader (XmlNode node) { source = new XmlNodeReaderImpl (node); } private XmlNodeReader (XmlNodeReaderImpl entityContainer, bool insideAttribute) { source = new XmlNodeReaderImpl (entityContainer); this.entityInsideAttribute = insideAttribute; } #endregion #region Properties private XmlReader Current { get { return entity != null && entity.ReadState != ReadState.Initial ? entity : source; } } public override int AttributeCount { get { return Current.AttributeCount; } } public override string BaseURI { get { return Current.BaseURI; } } #if NET_2_0 public override bool CanReadBinaryContent { get { return true; } } /* public override bool CanReadValueChunk { get { return true; } } */ #else internal override bool CanReadBinaryContent { get { return true; } } /* internal override bool CanReadValueChunk { get { return true; } } */ #endif public override bool CanResolveEntity { get { return true; } } public override int Depth { get { // On EndEntity, depth is the same as that // of EntityReference. if (entity != null && entity.ReadState == ReadState.Interactive) return source.Depth + entity.Depth + 1; else return source.Depth; } } public override bool EOF { get { return source.EOF; } } public override bool HasAttributes { get { return Current.HasAttributes; } } #if !MOONLIGHT public override bool HasValue { get { return Current.HasValue; } } #endif public override bool IsDefault { get { return Current.IsDefault; } } public override bool IsEmptyElement { get { return Current.IsEmptyElement; } } #if NET_2_0 #else public override string this [int i] { get { return GetAttribute (i); } } public override string this [string name] { get { return GetAttribute (name); } } public override string this [string name, string namespaceURI] { get { return GetAttribute (name, namespaceURI); } } #endif public override string LocalName { get { return Current.LocalName; } } public override string Name { get { return Current.Name; } } public override string NamespaceURI { get { return Current.NamespaceURI; } } public override XmlNameTable NameTable { get { return Current.NameTable; } } public override XmlNodeType NodeType { get { if (entity != null) return entity.ReadState == ReadState.Initial ? source.NodeType : entity.EOF ? XmlNodeType.EndEntity : entity.NodeType; else return source.NodeType; } } XmlParserContext IHasXmlParserContext.ParserContext { get { return ((IHasXmlParserContext) Current).ParserContext; } } public override string Prefix { get { return Current.Prefix; } } #if NET_2_0 #else public override char QuoteChar { get { return '"'; } } #endif public override ReadState ReadState { get { return entity != null ? ReadState.Interactive : source.ReadState; } } #if NET_2_0 public override IXmlSchemaInfo SchemaInfo { get { return entity != null ? entity.SchemaInfo : source.SchemaInfo; } } #endif public override string Value { get { return Current.Value; } } public override string XmlLang { get { return Current.XmlLang; } } public override XmlSpace XmlSpace { get { return Current.XmlSpace; } } #endregion #region Methods // If current entityReference is a child of an attribute, // then MoveToAttribute simply means that we no more need this entity Current. // Otherwise, this invokation means that // it is expected to move to resolved (maybe) element's attribute. // // This rule applies to many methods like MoveTo*Attribute(). public override void Close () { if (entity != null) entity.Close (); source.Close (); } public override string GetAttribute (int attributeIndex) { return Current.GetAttribute (attributeIndex); } public override string GetAttribute (string name) { return Current.GetAttribute (name); } public override string GetAttribute (string name, string namespaceURI) { return Current.GetAttribute (name, namespaceURI); } #if NET_2_0 IDictionary IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope) { return ((IXmlNamespaceResolver) Current).GetNamespacesInScope (scope); } #endif public override string LookupNamespace (string prefix) { return Current.LookupNamespace (prefix); } #if NET_2_0 string IXmlNamespaceResolver.LookupPrefix (string ns) { return ((IXmlNamespaceResolver) Current).LookupPrefix (ns); } #endif public override void MoveToAttribute (int i) { if (entity != null && entityInsideAttribute) { entity.Close (); entity = null; } Current.MoveToAttribute (i); insideAttribute = true; } public override bool MoveToAttribute (string name) { if (entity != null && !entityInsideAttribute) return entity.MoveToAttribute (name); if (!source.MoveToAttribute (name)) return false; if (entity != null && entityInsideAttribute) { entity.Close (); entity = null; } insideAttribute = true; return true; } public override bool MoveToAttribute (string localName, string namespaceURI) { if (entity != null && !entityInsideAttribute) return entity.MoveToAttribute (localName, namespaceURI); if (!source.MoveToAttribute (localName, namespaceURI)) return false; if (entity != null && entityInsideAttribute) { entity.Close (); entity = null; } insideAttribute = true; return true; } public override bool MoveToElement () { if (entity != null && entityInsideAttribute) entity = null; if (!Current.MoveToElement ()) return false; insideAttribute = false; return true; } public override bool MoveToFirstAttribute () { if (entity != null && !entityInsideAttribute) return entity.MoveToFirstAttribute (); if (!source.MoveToFirstAttribute ()) return false; if (entity != null && entityInsideAttribute) { entity.Close (); entity = null; } insideAttribute = true; return true; } public override bool MoveToNextAttribute () { if (entity != null && !entityInsideAttribute) return entity.MoveToNextAttribute (); if (!source.MoveToNextAttribute ()) return false; if (entity != null && entityInsideAttribute) { entity.Close (); entity = null; } insideAttribute = true; return true; } public override bool Read () { insideAttribute = false; if (entity != null && (entityInsideAttribute || entity.EOF)) entity = null; if (entity != null) { entity.Read (); return true; // either success or EndEntity } else return source.Read (); } public override bool ReadAttributeValue () { if (entity != null && entityInsideAttribute) { if (entity.EOF) entity = null; else { entity.Read (); return true; // either success or EndEntity } } return Current.ReadAttributeValue (); } #if NET_2_0 public override int ReadContentAsBase64 ( byte [] buffer, int offset, int length) { // return base.ReadContentAsBase64 ( // buffer, offset, length); // FIXME: This is problematic wrt end of entity. if (entity != null) return entity.ReadContentAsBase64 ( buffer, offset, length); else return source.ReadContentAsBase64 ( buffer, offset, length); } public override int ReadContentAsBinHex ( byte [] buffer, int offset, int length) { // return base.ReadContentAsBinHex ( // buffer, offset, length); // FIXME: This is problematic wrt end of entity. if (entity != null) return entity.ReadContentAsBinHex ( buffer, offset, length); else return source.ReadContentAsBinHex ( buffer, offset, length); } public override int ReadElementContentAsBase64 ( byte [] buffer, int offset, int length) { // return base.ReadElementContentAsBase64 ( // buffer, offset, length); // FIXME: This is problematic wrt end of entity. if (entity != null) return entity.ReadElementContentAsBase64 ( buffer, offset, length); else return source.ReadElementContentAsBase64 ( buffer, offset, length); } public override int ReadElementContentAsBinHex ( byte [] buffer, int offset, int length) { // return base.ReadElementContentAsBinHex ( // buffer, offset, length); // FIXME: This is problematic wrt end of entity. if (entity != null) return entity.ReadElementContentAsBinHex ( buffer, offset, length); else return source.ReadElementContentAsBinHex ( buffer, offset, length); } #endif public override string ReadString () { return base.ReadString (); } #if !MOONLIGHT public override void ResolveEntity () { if (entity != null) entity.ResolveEntity (); else { if (source.NodeType != XmlNodeType.EntityReference) throw new InvalidOperationException ("The current node is not an Entity Reference"); entity = new XmlNodeReader (source, insideAttribute); } } #endif public override void Skip () { if (entity != null && entityInsideAttribute) entity = null; Current.Skip (); } #endregion } }