XmlNodeReader.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. //
  2. // System.Xml.XmlNodeReader.cs
  3. //
  4. // Author:
  5. // Duncan Mak ([email protected])
  6. // Atsushi Enomoto ([email protected])
  7. //
  8. // (C) Ximian, Inc.
  9. // (C) Atsushi Enomoto
  10. //
  11. using System;
  12. using System.Collections;
  13. using System.Xml;
  14. using System.Text;
  15. namespace System.Xml
  16. {
  17. public class XmlNodeReader : XmlReader
  18. {
  19. XmlDocument document;
  20. XmlNode startNode;
  21. XmlNode current;
  22. ReadState state = ReadState.Initial;
  23. int depth;
  24. bool isEndElement;
  25. bool nextIsEndElement; // used for ReadString()
  26. bool alreadyRead;
  27. StringBuilder valueBuilder = new StringBuilder ();
  28. XmlNamespaceManager defaultNsmgr;
  29. Stack entityReaderStack = new Stack ();
  30. XmlTextReader entityReader;
  31. private XmlNode ownerLinkedNode {
  32. get {
  33. if (current.ParentNode != null && current.ParentNode.NodeType == XmlNodeType.Attribute)
  34. return ((XmlAttribute) current.ParentNode).OwnerElement;
  35. else if (current.NodeType == XmlNodeType.Attribute)
  36. return ((XmlAttribute) current).OwnerElement;
  37. else
  38. return current;
  39. }
  40. }
  41. #region Constructor
  42. public XmlNodeReader (XmlNode node)
  43. {
  44. startNode = node;
  45. document = startNode.NodeType == XmlNodeType.Document ?
  46. startNode as XmlDocument : startNode.OwnerDocument;
  47. if (node.NodeType != XmlNodeType.Document
  48. && node.NodeType != XmlNodeType.DocumentFragment)
  49. alreadyRead = true;
  50. defaultNsmgr = new XmlNamespaceManager (this.NameTable);
  51. }
  52. #endregion
  53. #region Properties
  54. public override int AttributeCount {
  55. get {
  56. if (entityReader != null)
  57. return entityReader.ReadState == ReadState.Interactive ?
  58. entityReader.AttributeCount : 0;
  59. if (isEndElement || current == null)
  60. return 0;
  61. XmlNode n = ownerLinkedNode;
  62. return n.Attributes != null ? n.Attributes.Count : 0;
  63. }
  64. }
  65. public override string BaseURI {
  66. get {
  67. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  68. return entityReader.BaseURI;
  69. if (current == null)
  70. return String.Empty;
  71. return current.BaseURI;
  72. }
  73. }
  74. public override bool CanResolveEntity {
  75. get {
  76. return true;
  77. }
  78. }
  79. public override int Depth {
  80. get {
  81. if (entityReader != null && entityReader.ReadState == ReadState.Interactive)
  82. return entityReader.Depth + depth + entityReaderStack.Count + 1;
  83. if (current == null)
  84. return 0;
  85. if (current.NodeType == XmlNodeType.Attribute)
  86. return depth + 1;
  87. if (current.ParentNode != null && current.ParentNode.NodeType == XmlNodeType.Attribute)
  88. return depth + 2;
  89. return depth;
  90. }
  91. }
  92. public override bool EOF {
  93. get {
  94. return this.ReadState == ReadState.EndOfFile
  95. || this.ReadState == ReadState.Error;
  96. }
  97. }
  98. public override bool HasAttributes {
  99. get {
  100. if (entityReader != null)
  101. return entityReader.ReadState == ReadState.Interactive ?
  102. entityReader.HasAttributes : false;
  103. if (isEndElement || current == null)
  104. return false;
  105. // MS BUG: inconsistent return value between XmlTextReader and XmlNodeReader.
  106. // As for attribute and its descendants, XmlReader returns element's HasAttributes.
  107. XmlNode n = ownerLinkedNode;
  108. if (n.Attributes == null ||
  109. n.Attributes.Count == 0)
  110. return false;
  111. else
  112. return true;
  113. }
  114. }
  115. public override bool HasValue {
  116. get {
  117. if (entityReader != null)
  118. return entityReader.ReadState == ReadState.Interactive ?
  119. entityReader.IsDefault : false;
  120. if (current == null)
  121. return false;
  122. switch (current.NodeType) {
  123. case XmlNodeType.Element:
  124. case XmlNodeType.EntityReference:
  125. case XmlNodeType.Document:
  126. case XmlNodeType.DocumentFragment:
  127. case XmlNodeType.Notation:
  128. case XmlNodeType.EndElement:
  129. case XmlNodeType.EndEntity:
  130. return false;
  131. default:
  132. return true;
  133. }
  134. }
  135. }
  136. public override bool IsDefault {
  137. get {
  138. if (entityReader != null)
  139. return entityReader.ReadState == ReadState.Interactive ?
  140. entityReader.IsDefault : false;
  141. if (current == null)
  142. return false;
  143. if (current.NodeType != XmlNodeType.Attribute)
  144. return false;
  145. else
  146. {
  147. return ((XmlAttribute) current).isDefault;
  148. }
  149. }
  150. }
  151. public override bool IsEmptyElement {
  152. get {
  153. if (entityReader != null)
  154. return entityReader.ReadState == ReadState.Interactive ?
  155. entityReader.IsDefault : false;
  156. if (current == null)
  157. return false;
  158. if(current.NodeType == XmlNodeType.Element)
  159. return ((XmlElement) current).IsEmpty;
  160. else
  161. return false;
  162. }
  163. }
  164. public override string this [int i] {
  165. get { return GetAttribute (i); }
  166. }
  167. public override string this [string name] {
  168. get { return GetAttribute (name); }
  169. }
  170. public override string this [string name, string namespaceURI] {
  171. get { return GetAttribute (name, namespaceURI); }
  172. }
  173. public override string LocalName {
  174. get {
  175. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  176. return entityReader.LocalName;
  177. if (current == null)
  178. return String.Empty;
  179. switch (current.NodeType) {
  180. case XmlNodeType.Attribute:
  181. case XmlNodeType.DocumentType:
  182. case XmlNodeType.Element:
  183. case XmlNodeType.EntityReference:
  184. case XmlNodeType.ProcessingInstruction:
  185. case XmlNodeType.XmlDeclaration:
  186. return current.LocalName;
  187. }
  188. return String.Empty;
  189. }
  190. }
  191. public override string Name {
  192. get {
  193. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  194. return entityReader.Name;
  195. if (current == null)
  196. return String.Empty;
  197. switch (current.NodeType) {
  198. case XmlNodeType.Attribute:
  199. case XmlNodeType.DocumentType:
  200. case XmlNodeType.Element:
  201. case XmlNodeType.EntityReference:
  202. case XmlNodeType.ProcessingInstruction:
  203. case XmlNodeType.XmlDeclaration:
  204. return current.Name;
  205. }
  206. return String.Empty;
  207. }
  208. }
  209. public override string NamespaceURI {
  210. get {
  211. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  212. return entityReader.NamespaceURI;
  213. if (current == null)
  214. return String.Empty;
  215. return current.NamespaceURI;
  216. }
  217. }
  218. public override XmlNameTable NameTable {
  219. get { return document.NameTable; }
  220. }
  221. public override XmlNodeType NodeType {
  222. get {
  223. if (entityReader != null)
  224. switch (entityReader.ReadState) {
  225. case ReadState.Interactive:
  226. return entityReader.NodeType;
  227. case ReadState.Initial:
  228. return XmlNodeType.EntityReference;
  229. case ReadState.EndOfFile:
  230. return XmlNodeType.EndEntity;
  231. }
  232. if (current == null)
  233. return XmlNodeType.None;
  234. return isEndElement ? XmlNodeType.EndElement : current.NodeType;
  235. }
  236. }
  237. public override string Prefix {
  238. get {
  239. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  240. return entityReader.Prefix;
  241. if (current == null)
  242. return String.Empty;
  243. // if (current.NodeType == XmlNodeType.Attribute)
  244. // return current.Prefix != String.Empty ? current.Prefix : null;
  245. // else
  246. return current.Prefix;
  247. }
  248. }
  249. public override char QuoteChar {
  250. get {
  251. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  252. return entityReader.QuoteChar;
  253. return '"';
  254. }
  255. }
  256. public override ReadState ReadState {
  257. get { return state; }
  258. }
  259. public override string Value {
  260. get {
  261. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  262. return entityReader.Value;
  263. if (NodeType == XmlNodeType.DocumentType)
  264. return ((XmlDocumentType) current).InternalSubset;
  265. else
  266. return HasValue ? current.Value : String.Empty;
  267. }
  268. }
  269. public override string XmlLang {
  270. get {
  271. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  272. return entityReader.XmlLang;
  273. if (current == null)
  274. return String.Empty;
  275. return current.XmlLang;
  276. }
  277. }
  278. public override XmlSpace XmlSpace {
  279. get {
  280. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  281. return entityReader.XmlSpace;
  282. if (current == null)
  283. return XmlSpace.None;
  284. return current.XmlSpace;
  285. }
  286. }
  287. #endregion
  288. #region Methods
  289. // If current entityReference is a child of an attribute,
  290. // then MoveToAttribute simply means that we no more need this entity reader.
  291. // Otherwise, this invokation means that
  292. // it is expected to move to resolved (maybe) element's attribute.
  293. //
  294. // This rule applies to many methods like MoveTo*Attribute().
  295. private bool CheckAndResetEntityReaderOnMoveToAttribute ()
  296. {
  297. if (entityReader == null)
  298. return false;
  299. if (current != null && current.ParentNode != null &&
  300. current.ParentNode.NodeType == XmlNodeType.Attribute) {
  301. entityReader.Close ();
  302. entityReader = entityReaderStack.Count > 0 ?
  303. entityReaderStack.Pop () as XmlTextReader : null;
  304. return true;
  305. }
  306. else
  307. return false;
  308. }
  309. public override void Close ()
  310. {
  311. if (entityReader != null)
  312. entityReader.Close ();
  313. while (entityReaderStack.Count > 0)
  314. ((XmlTextReader) entityReaderStack.Pop ()).Close ();
  315. current = null;
  316. state = ReadState.Closed;
  317. }
  318. public override string GetAttribute (int attributeIndex)
  319. {
  320. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  321. return entityReader.GetAttribute (attributeIndex);
  322. if (NodeType == XmlNodeType.XmlDeclaration) {
  323. XmlDeclaration decl = current as XmlDeclaration;
  324. if (attributeIndex == 0)
  325. return decl.Version;
  326. else if (attributeIndex == 1) {
  327. if (decl.Encoding != String.Empty)
  328. return decl.Encoding;
  329. else if (decl.Standalone != String.Empty)
  330. return decl.Standalone;
  331. }
  332. else if (attributeIndex == 2 &&
  333. decl.Encoding != String.Empty && decl.Standalone != null)
  334. return decl.Standalone;
  335. throw new ArgumentOutOfRangeException ("Index out of range.");
  336. } else if (NodeType == XmlNodeType.DocumentType) {
  337. XmlDocumentType doctype = current as XmlDocumentType;
  338. if (attributeIndex == 0) {
  339. if (doctype.PublicId != "")
  340. return doctype.PublicId;
  341. else if (doctype.SystemId != "")
  342. return doctype.SystemId;
  343. } else if (attributeIndex == 1)
  344. if (doctype.PublicId == "" && doctype.SystemId != "")
  345. return doctype.SystemId;
  346. throw new ArgumentOutOfRangeException ("Index out of range.");
  347. }
  348. // This is MS.NET bug which returns attributes in spite of EndElement.
  349. if (isEndElement || current == null)
  350. return null;
  351. if (attributeIndex < 0 || attributeIndex > AttributeCount)
  352. throw new ArgumentOutOfRangeException ("Index out of range.");
  353. return ownerLinkedNode.Attributes [attributeIndex].Value;
  354. }
  355. public override string GetAttribute (string name)
  356. {
  357. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  358. return entityReader.GetAttribute (name);
  359. // This is MS.NET bug which returns attributes in spite of EndElement.
  360. if (isEndElement || current == null)
  361. return null;
  362. if (NodeType == XmlNodeType.XmlDeclaration)
  363. return GetXmlDeclarationAttribute (name);
  364. else if (NodeType == XmlNodeType.DocumentType)
  365. return GetDocumentTypeAttribute (name);
  366. if (ownerLinkedNode.Attributes == null)
  367. return null;
  368. XmlAttribute attr = ownerLinkedNode.Attributes [name];
  369. if (attr == null)
  370. return null;
  371. else
  372. return attr.Value;
  373. }
  374. public override string GetAttribute (string name, string namespaceURI)
  375. {
  376. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  377. return entityReader.GetAttribute (name, namespaceURI);
  378. // This is MS.NET bug which returns attributes in spite of EndElement.
  379. if (isEndElement || current == null)
  380. return null;
  381. if (NodeType == XmlNodeType.XmlDeclaration)
  382. return GetXmlDeclarationAttribute (name);
  383. else if (NodeType == XmlNodeType.DocumentType)
  384. return GetDocumentTypeAttribute (name);
  385. if (ownerLinkedNode.Attributes == null)
  386. return null;
  387. XmlAttribute attr = ownerLinkedNode.Attributes [name, namespaceURI];
  388. if (attr == null)
  389. return null; // In fact MS.NET returns null instead of String.Empty.
  390. else
  391. return attr.Value;
  392. }
  393. private string GetXmlDeclarationAttribute (string name)
  394. {
  395. XmlDeclaration decl = current as XmlDeclaration;
  396. switch (name) {
  397. case "version":
  398. return decl.Version;
  399. case "encoding":
  400. // This is MS.NET bug that XmlNodeReturns in case of string.empty.
  401. return decl.Encoding != String.Empty ? decl.Encoding : null;
  402. case "standalone":
  403. return decl.Standalone;
  404. }
  405. return null;
  406. }
  407. private string GetDocumentTypeAttribute (string name)
  408. {
  409. XmlDocumentType doctype = current as XmlDocumentType;
  410. switch (name) {
  411. case "PUBLIC":
  412. return doctype.PublicId;
  413. case "SYSTEM":
  414. return doctype.SystemId;
  415. }
  416. return null;
  417. }
  418. internal XmlParserContext GetInternalParserContext ()
  419. {
  420. if (entityReader != null)
  421. return entityReader.GetInternalParserContext ();
  422. else
  423. return new XmlParserContext (document.NameTable,
  424. current.ConstructNamespaceManager (),
  425. document.DocumentType != null ? document.DocumentType.DTD : null,
  426. current.BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
  427. }
  428. public override string LookupNamespace (string prefix)
  429. {
  430. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  431. return entityReader.LookupNamespace (prefix);
  432. if (current == null)
  433. return null;
  434. XmlAttribute curAttr = current as XmlAttribute;
  435. XmlNode target = curAttr != null ? curAttr.OwnerElement : current;
  436. if (prefix == "") {
  437. do {
  438. XmlAttribute attr = target.Attributes ["xmlns"];
  439. if (attr != null)
  440. return attr.Value;
  441. target = target.ParentNode;
  442. } while (target.NodeType != XmlNodeType.Document);
  443. } else {
  444. string name = "xmlns:" + prefix;
  445. do {
  446. XmlAttribute attr = target.Attributes [name];
  447. if (attr != null)
  448. return attr.Value;
  449. target = target.ParentNode;
  450. } while (target.NodeType != XmlNodeType.Document);
  451. }
  452. return defaultNsmgr.LookupNamespace (prefix, false);
  453. }
  454. public override void MoveToAttribute (int attributeIndex)
  455. {
  456. if (entityReader != null) {
  457. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ()) {
  458. entityReader.MoveToAttribute (attributeIndex);
  459. return;
  460. }
  461. // And in case of abondoning entityReader, go on...
  462. }
  463. if (isEndElement || attributeIndex < 0 || attributeIndex > AttributeCount)
  464. throw new ArgumentOutOfRangeException ();
  465. state = ReadState.Interactive;
  466. current = ownerLinkedNode.Attributes [attributeIndex];
  467. }
  468. public override bool MoveToAttribute (string name)
  469. {
  470. if (entityReader != null) {
  471. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  472. return entityReader.MoveToAttribute (name);
  473. // And in case of abondoning entityReader, go on...
  474. }
  475. if (isEndElement || current == null)
  476. return false;
  477. XmlNode tmpCurrent = current;
  478. if (current.ParentNode.NodeType == XmlNodeType.Attribute)
  479. current = current.ParentNode;
  480. if (ownerLinkedNode.Attributes == null)
  481. return false;
  482. XmlAttribute attr = ownerLinkedNode.Attributes [name];
  483. if (attr == null) {
  484. current = tmpCurrent;
  485. return false;
  486. }
  487. else {
  488. current = attr;
  489. return true;
  490. }
  491. }
  492. public override bool MoveToAttribute (string name, string namespaceURI)
  493. {
  494. if (entityReader != null) {
  495. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  496. return entityReader.MoveToAttribute (name, namespaceURI);
  497. // And in case of abondoning entityReader, go on...
  498. }
  499. if (isEndElement || current == null)
  500. return false;
  501. if (ownerLinkedNode.Attributes == null)
  502. return false;
  503. XmlAttribute attr = ownerLinkedNode.Attributes [name, namespaceURI];
  504. if (attr == null)
  505. return false;
  506. else {
  507. current = attr;
  508. return true;
  509. }
  510. }
  511. private void MoveToParentElement ()
  512. {
  513. // This is buggy. It is not only the case when EndElement = true.
  514. isEndElement = true;
  515. depth--;
  516. current = current.ParentNode;
  517. }
  518. public override bool MoveToElement ()
  519. {
  520. if (entityReader != null) {
  521. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  522. return entityReader.MoveToElement ();
  523. // And in case of abondoning entityReader, go on...
  524. }
  525. if (current == null)
  526. return false;
  527. XmlNode n = ownerLinkedNode;
  528. if (current != n) {
  529. current = n;
  530. return true;
  531. } else
  532. return false;
  533. }
  534. public override bool MoveToFirstAttribute ()
  535. {
  536. if (entityReader != null) {
  537. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  538. return entityReader.MoveToFirstAttribute ();
  539. // And in case of abondoning entityReader, go on...
  540. }
  541. if (current == null)
  542. return false;
  543. if (ownerLinkedNode.Attributes == null)
  544. return false;
  545. if(ownerLinkedNode.Attributes.Count > 0)
  546. {
  547. current = ownerLinkedNode.Attributes [0];
  548. return true;
  549. }
  550. else
  551. return false;
  552. }
  553. public override bool MoveToNextAttribute ()
  554. {
  555. if (entityReader != null) {
  556. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  557. return entityReader.MoveToNextAttribute ();
  558. // And in case of abondoning entityReader, go on...
  559. }
  560. if (current == null)
  561. return false;
  562. if (current.NodeType != XmlNodeType.Attribute)
  563. return MoveToFirstAttribute ();
  564. else
  565. {
  566. XmlAttributeCollection ac = ((XmlAttribute) current).OwnerElement.Attributes;
  567. for (int i=0; i<ac.Count-1; i++)
  568. {
  569. XmlAttribute attr = ac [i];
  570. if (attr == current)
  571. {
  572. i++;
  573. if (i == ac.Count)
  574. return false;
  575. current = ac [i];
  576. return true;
  577. }
  578. }
  579. return false;
  580. }
  581. }
  582. private bool MoveToNextSibling ()
  583. {
  584. if (nextIsEndElement) {
  585. // nextIsEndElement is set only by ReadString.
  586. nextIsEndElement = false;
  587. MoveToParentElement ();
  588. } else if (alreadyRead) {
  589. alreadyRead = false;
  590. return current != null;
  591. }
  592. if (current.NextSibling != null) {
  593. isEndElement = false;
  594. current = current.NextSibling;
  595. } else {
  596. MoveToParentElement ();
  597. }
  598. if (current == null) {
  599. state = ReadState.EndOfFile;
  600. return false;
  601. }
  602. else
  603. return true;
  604. }
  605. public override bool Read ()
  606. {
  607. if (EOF)
  608. return false;
  609. this.CheckAndResetEntityReaderOnMoveToAttribute ();
  610. if (entityReader != null) {
  611. // Read finalizes entity reader.
  612. switch (entityReader.ReadState) {
  613. case ReadState.Interactive:
  614. case ReadState.Initial:
  615. // If it is ended, then other properties/methods will take care.
  616. entityReader.Read ();
  617. return true;
  618. default:
  619. entityReader = entityReaderStack.Count > 0 ?
  620. entityReaderStack.Pop () as XmlTextReader : null;
  621. return Read ();
  622. }
  623. // and go on ...
  624. }
  625. if (ReadState == ReadState.Initial) {
  626. current = startNode;
  627. state = ReadState.Interactive;
  628. // when startNode is document or fragment
  629. if (!alreadyRead)
  630. current = startNode.FirstChild;
  631. else
  632. alreadyRead = false;
  633. if (current == null) {
  634. state = ReadState.Error;
  635. return false;
  636. } else
  637. return true;
  638. }
  639. MoveToElement ();
  640. if (IsEmptyElement || isEndElement) {
  641. // Then go up and move to next.
  642. // If no more nodes, then set EOF.
  643. isEndElement = false;
  644. if (current.ParentNode == null
  645. || current.ParentNode.NodeType == XmlNodeType.Document
  646. || current.ParentNode.NodeType == XmlNodeType.DocumentFragment) {
  647. current = null;
  648. state = ReadState.EndOfFile;
  649. return false;
  650. } else if (current.NextSibling == null) {
  651. depth--;
  652. current = current.ParentNode;
  653. isEndElement = true;
  654. return true;
  655. } else {
  656. current = current.NextSibling;
  657. return true;
  658. }
  659. } else if (nextIsEndElement) {
  660. // nextIsEndElement is set only by ReadString.
  661. nextIsEndElement = false;
  662. isEndElement = true;
  663. return current != null;
  664. } else if (alreadyRead) {
  665. alreadyRead = false;
  666. return current != null;
  667. }
  668. if (!isEndElement && current.FirstChild != null && current.NodeType != XmlNodeType.EntityReference) {
  669. isEndElement = false;
  670. current = current.FirstChild;
  671. depth++;
  672. } else if (current.NodeType == XmlNodeType.Element) {
  673. isEndElement = true;
  674. if (current.FirstChild != null)
  675. depth--;
  676. } else
  677. MoveToNextSibling ();
  678. return current != null;
  679. }
  680. public override bool ReadAttributeValue ()
  681. {
  682. if (entityReader != null) {
  683. switch (entityReader.ReadState) {
  684. case ReadState.Interactive:
  685. case ReadState.Initial:
  686. // If it is ended, then other properties/methods will take care.
  687. return entityReader.ReadAttributeValue ();
  688. default:
  689. entityReader = entityReaderStack.Count > 0 ?
  690. entityReaderStack.Pop () as XmlTextReader : null;
  691. // and go on ...
  692. return ReadAttributeValue ();
  693. }
  694. }
  695. if (current.NodeType == XmlNodeType.Attribute) {
  696. if (current.FirstChild == null)
  697. return false;
  698. current = current.FirstChild;
  699. return true;
  700. } else if (current.ParentNode.NodeType == XmlNodeType.Attribute) {
  701. if (current.NextSibling == null)
  702. return false;
  703. current = current.NextSibling;
  704. return true;
  705. } else
  706. return false;
  707. }
  708. #if NET_1_0
  709. // Its traversal behavior is almost same as Read().
  710. public override string ReadInnerXml ()
  711. {
  712. if (entityReader != null) {
  713. if (entityReader.EOF) {
  714. entityReader = entityReaderStack.Count > 0 ?
  715. entityReaderStack.Pop () as XmlTextReader : null;
  716. return ReadInnerXml ();
  717. } else
  718. return entityReader.ReadInnerXml ();
  719. }
  720. if (this.state != ReadState.Interactive)
  721. return String.Empty;
  722. XmlNode initial = current;
  723. // Almost copied from XmlTextReader.
  724. switch (NodeType) {
  725. case XmlNodeType.Attribute:
  726. return Value;
  727. case XmlNodeType.Element:
  728. if (IsEmptyElement)
  729. return String.Empty;
  730. int startDepth = depth;
  731. bool loop = true;
  732. do {
  733. Read ();
  734. if (NodeType ==XmlNodeType.None)
  735. throw new XmlException ("unexpected end of xml.");
  736. else if (NodeType == XmlNodeType.EndElement && depth == startDepth) {
  737. loop = false;
  738. Read ();
  739. }
  740. } while (loop);
  741. return initial.InnerXml;
  742. case XmlNodeType.None:
  743. return String.Empty;
  744. default:
  745. Read ();
  746. return String.Empty;
  747. }
  748. }
  749. // Its traversal behavior is almost same as Read().
  750. public override string ReadOuterXml ()
  751. {
  752. if (entityReader != null) {
  753. if (entityReader.EOF) {
  754. entityReader = entityReaderStack.Count > 0 ?
  755. entityReaderStack.Pop () as XmlTextReader : null;
  756. return ReadOuterXml ();
  757. } else
  758. return entityReader.ReadOuterXml ();
  759. }
  760. if (NodeType == XmlNodeType.EndElement)
  761. return String.Empty;
  762. XmlNode initial = current;
  763. switch (NodeType) {
  764. case XmlNodeType.Attribute:
  765. return current.OuterXml;
  766. case XmlNodeType.Element:
  767. if (NodeType == XmlNodeType.Element && !IsEmptyElement)
  768. ReadInnerXml ();
  769. else
  770. Read ();
  771. return initial.OuterXml;
  772. case XmlNodeType.None:
  773. return String.Empty;
  774. default:
  775. Read ();
  776. return String.Empty;
  777. }
  778. }
  779. #endif
  780. public override string ReadString ()
  781. {
  782. return ReadStringInternal ();
  783. }
  784. public override void ResolveEntity ()
  785. {
  786. if (NodeType != XmlNodeType.EntityReference)
  787. throw new InvalidOperationException ("The current node is not an Entity Reference");
  788. // FIXME: Now that XmlEntityReference holds the target
  789. // entity's child nodes, we don't have to use
  790. // XmlTextReader and simply use those nodes directly.
  791. string replacementText = current.InnerXml;
  792. XmlNodeType xmlReaderNodeType =
  793. (current.ParentNode != null && current.ParentNode.NodeType == XmlNodeType.Attribute) ?
  794. XmlNodeType.Attribute : XmlNodeType.Element;
  795. XmlParserContext ctx = null;
  796. if (entityReader != null) {
  797. entityReaderStack.Push (entityReader);
  798. ctx = entityReader.GetInternalParserContext ();
  799. }
  800. if (ctx == null) {
  801. ctx = new XmlParserContext (document.NameTable,
  802. current.ConstructNamespaceManager (),
  803. document.DocumentType != null ? document.DocumentType.DTD : null,
  804. BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
  805. }
  806. entityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
  807. entityReader.XmlResolver = document.Resolver;
  808. entityReader.SkipTextDeclaration ();
  809. }
  810. public override void Skip ()
  811. {
  812. // Why is this overriden? Such skipping might raise
  813. // (or ignore) unexpected validation error.
  814. base.Skip ();
  815. }
  816. #endregion
  817. }
  818. }