2 // System.Xml.XmlNodeReader2.cs - splitted XmlNodeReader that manages entities.
5 // Duncan Mak (duncan@ximian.com)
6 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections.Generic;
38 using System.Xml.Schema;
45 public class XmlNodeReader : XmlReader, IHasXmlParserContext, IXmlNamespaceResolver
47 public class XmlNodeReader : XmlReader, IHasXmlParserContext
51 XmlNodeReaderImpl source;
52 bool entityInsideAttribute;
57 public XmlNodeReader (XmlNode node)
59 source = new XmlNodeReaderImpl (node);
62 private XmlNodeReader (XmlNodeReaderImpl entityContainer, bool insideAttribute)
64 source = new XmlNodeReaderImpl (entityContainer);
65 this.entityInsideAttribute = insideAttribute;
72 private XmlReader Current {
73 get { return entity != null && entity.ReadState != ReadState.Initial ? entity : source; }
76 public override int AttributeCount {
77 get { return Current.AttributeCount; }
80 public override string BaseURI {
81 get { return Current.BaseURI; }
85 public override bool CanReadBinaryContent {
90 public override bool CanReadValueChunk {
95 internal override bool CanReadBinaryContent {
100 internal override bool CanReadValueChunk {
106 public override bool CanResolveEntity {
110 public override int Depth {
112 // On EndEntity, depth is the same as that
113 // of EntityReference.
114 if (entity != null && entity.ReadState == ReadState.Interactive)
115 return source.Depth + entity.Depth + 1;
121 public override bool EOF {
122 get { return source.EOF; }
125 public override bool HasAttributes {
126 get { return Current.HasAttributes; }
129 public override bool HasValue {
130 get { return Current.HasValue; }
133 public override bool IsDefault {
134 get { return Current.IsDefault; }
137 public override bool IsEmptyElement {
138 get { return Current.IsEmptyElement; }
143 public override string this [int i] {
144 get { return GetAttribute (i); }
147 public override string this [string name] {
148 get { return GetAttribute (name); }
151 public override string this [string name, string namespaceURI] {
152 get { return GetAttribute (name, namespaceURI); }
156 public override string LocalName {
157 get { return Current.LocalName; }
160 public override string Name {
161 get { return Current.Name; }
164 public override string NamespaceURI {
165 get { return Current.NamespaceURI; }
168 public override XmlNameTable NameTable {
169 get { return Current.NameTable; }
172 public override XmlNodeType NodeType {
174 if (Current == entity)
175 return entity.EOF ? XmlNodeType.EndEntity : entity.NodeType;
177 return source.NodeType;
181 XmlParserContext IHasXmlParserContext.ParserContext {
182 get { return ((IHasXmlParserContext) Current).ParserContext; }
185 public override string Prefix {
186 get { return Current.Prefix; }
191 public override char QuoteChar {
196 public override ReadState ReadState {
197 get { return entity != null ? ReadState.Interactive : source.ReadState; }
201 public override IXmlSchemaInfo SchemaInfo {
202 get { return entity != null ? entity.SchemaInfo : source.SchemaInfo; }
206 public override string Value {
207 get { return Current.Value; }
210 public override string XmlLang {
211 get { return Current.XmlLang; }
214 public override XmlSpace XmlSpace {
215 get { return Current.XmlSpace; }
221 // If current entityReference is a child of an attribute,
222 // then MoveToAttribute simply means that we no more need this entity Current.
223 // Otherwise, this invokation means that
224 // it is expected to move to resolved (maybe) element's attribute.
226 // This rule applies to many methods like MoveTo*Attribute().
228 public override void Close ()
235 public override string GetAttribute (int attributeIndex)
237 return Current.GetAttribute (attributeIndex);
240 public override string GetAttribute (string name)
242 return Current.GetAttribute (name);
245 public override string GetAttribute (string name, string namespaceURI)
247 return Current.GetAttribute (name, namespaceURI);
251 IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope)
253 return ((IXmlNamespaceResolver) Current).GetNamespacesInScope (scope);
257 public override string LookupNamespace (string prefix)
259 return Current.LookupNamespace (prefix);
263 string IXmlNamespaceResolver.LookupPrefix (string ns)
265 return ((IXmlNamespaceResolver) Current).LookupPrefix (ns);
269 public override void MoveToAttribute (int i)
271 if (entity != null && entityInsideAttribute) {
275 Current.MoveToAttribute (i);
276 insideAttribute = true;
279 public override bool MoveToAttribute (string name)
281 if (entity != null && !entityInsideAttribute)
282 return entity.MoveToAttribute (name);
283 if (!source.MoveToAttribute (name))
285 if (entity != null && entityInsideAttribute) {
289 insideAttribute = true;
293 public override bool MoveToAttribute (string localName, string namespaceURI)
295 if (entity != null && !entityInsideAttribute)
296 return entity.MoveToAttribute (localName, namespaceURI);
297 if (!source.MoveToAttribute (localName, namespaceURI))
299 if (entity != null && entityInsideAttribute) {
303 insideAttribute = true;
307 public override bool MoveToElement ()
309 if (entity != null && entityInsideAttribute)
311 if (!Current.MoveToElement ())
313 insideAttribute = false;
317 public override bool MoveToFirstAttribute ()
319 if (entity != null && !entityInsideAttribute)
320 return entity.MoveToFirstAttribute ();
321 if (!source.MoveToFirstAttribute ())
323 if (entity != null && entityInsideAttribute) {
327 insideAttribute = true;
331 public override bool MoveToNextAttribute ()
333 if (entity != null && !entityInsideAttribute)
334 return entity.MoveToNextAttribute ();
335 if (!source.MoveToNextAttribute ())
337 if (entity != null && entityInsideAttribute) {
341 insideAttribute = true;
345 public override bool Read ()
347 insideAttribute = false;
348 if (entity != null && (entityInsideAttribute || entity.EOF))
350 if (entity != null) {
352 return true; // either success or EndEntity
355 return source.Read ();
358 public override bool ReadAttributeValue ()
360 if (entity != null && entityInsideAttribute) {
365 return true; // either success or EndEntity
368 return Current.ReadAttributeValue ();
372 public override int ReadContentAsBase64 (
373 byte [] buffer, int offset, int length)
375 // return base.ReadContentAsBase64 (
376 // buffer, offset, length);
377 // FIXME: This is problematic wrt end of entity.
379 return entity.ReadContentAsBase64 (
380 buffer, offset, length);
382 return source.ReadContentAsBase64 (
383 buffer, offset, length);
386 public override int ReadContentAsBinHex (
387 byte [] buffer, int offset, int length)
389 // return base.ReadContentAsBinHex (
390 // buffer, offset, length);
391 // FIXME: This is problematic wrt end of entity.
393 return entity.ReadContentAsBinHex (
394 buffer, offset, length);
396 return source.ReadContentAsBinHex (
397 buffer, offset, length);
400 public override int ReadElementContentAsBase64 (
401 byte [] buffer, int offset, int length)
403 // return base.ReadElementContentAsBase64 (
404 // buffer, offset, length);
405 // FIXME: This is problematic wrt end of entity.
407 return entity.ReadElementContentAsBase64 (
408 buffer, offset, length);
410 return source.ReadElementContentAsBase64 (
411 buffer, offset, length);
414 public override int ReadElementContentAsBinHex (
415 byte [] buffer, int offset, int length)
417 // return base.ReadElementContentAsBinHex (
418 // buffer, offset, length);
419 // FIXME: This is problematic wrt end of entity.
421 return entity.ReadElementContentAsBinHex (
422 buffer, offset, length);
424 return source.ReadElementContentAsBinHex (
425 buffer, offset, length);
430 public override string ReadInnerXml ()
432 return ReadInnerXmlInternal ();
435 public override string ReadOuterXml ()
437 return ReadOuterXmlInternal ();
441 public override string ReadString ()
443 return ReadStringInternal ();
446 public override void ResolveEntity ()
449 entity.ResolveEntity ();
451 if (source.NodeType != XmlNodeType.EntityReference)
452 throw new InvalidOperationException ("The current node is not an Entity Reference");
453 entity = new XmlNodeReader (source, insideAttribute);
457 public override void Skip ()
459 if (entity != null && entityInsideAttribute)