XmlNodeReader.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  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 ownerElement {
  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 = ownerElement;
  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 = ownerElement;
  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 ownerElement.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. XmlAttribute attr = ownerElement.Attributes [name];
  367. if (attr == null)
  368. return null;
  369. else
  370. return attr.Value;
  371. }
  372. public override string GetAttribute (string name, string namespaceURI)
  373. {
  374. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  375. return entityReader.GetAttribute (name, namespaceURI);
  376. // This is MS.NET bug which returns attributes in spite of EndElement.
  377. if (isEndElement || current == null)
  378. return null;
  379. if (NodeType == XmlNodeType.XmlDeclaration)
  380. return GetXmlDeclarationAttribute (name);
  381. else if (NodeType == XmlNodeType.DocumentType)
  382. return GetDocumentTypeAttribute (name);
  383. XmlAttribute attr = ownerElement.Attributes [name, namespaceURI];
  384. if (attr == null)
  385. return null; // In fact MS.NET returns null instead of String.Empty.
  386. else
  387. return attr.Value;
  388. }
  389. private string GetXmlDeclarationAttribute (string name)
  390. {
  391. XmlDeclaration decl = current as XmlDeclaration;
  392. switch (name) {
  393. case "version":
  394. return decl.Version;
  395. case "encoding":
  396. // This is MS.NET bug that XmlNodeReturns in case of string.empty.
  397. return decl.Encoding != String.Empty ? decl.Encoding : null;
  398. case "standalone":
  399. return decl.Standalone;
  400. }
  401. return null;
  402. }
  403. private string GetDocumentTypeAttribute (string name)
  404. {
  405. XmlDocumentType doctype = current as XmlDocumentType;
  406. switch (name) {
  407. case "PUBLIC":
  408. return doctype.PublicId;
  409. case "SYSTEM":
  410. return doctype.SystemId;
  411. }
  412. return null;
  413. }
  414. internal XmlParserContext GetInternalParserContext ()
  415. {
  416. if (entityReader != null)
  417. return entityReader.GetInternalParserContext ();
  418. else
  419. return new XmlParserContext (document.NameTable,
  420. current.ConstructNamespaceManager (),
  421. document.DocumentType != null ? document.DocumentType.DTD : null,
  422. current.BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
  423. }
  424. public override string LookupNamespace (string prefix)
  425. {
  426. if (entityReader != null && entityReader.ReadState != ReadState.Initial)
  427. return entityReader.LookupNamespace (prefix);
  428. if (current == null)
  429. return null;
  430. XmlAttribute curAttr = current as XmlAttribute;
  431. XmlNode target = curAttr != null ? curAttr.OwnerElement : current;
  432. if (prefix == "") {
  433. do {
  434. XmlAttribute attr = target.Attributes ["xmlns"];
  435. if (attr != null)
  436. return attr.Value;
  437. target = target.ParentNode;
  438. } while (target.NodeType != XmlNodeType.Document);
  439. } else {
  440. string name = "xmlns:" + prefix;
  441. do {
  442. XmlAttribute attr = target.Attributes [name];
  443. if (attr != null)
  444. return attr.Value;
  445. target = target.ParentNode;
  446. } while (target.NodeType != XmlNodeType.Document);
  447. }
  448. return defaultNsmgr.LookupNamespace (prefix);
  449. }
  450. public override void MoveToAttribute (int attributeIndex)
  451. {
  452. if (entityReader != null) {
  453. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ()) {
  454. entityReader.MoveToAttribute (attributeIndex);
  455. return;
  456. }
  457. // And in case of abondoning entityReader, go on...
  458. }
  459. if (isEndElement || attributeIndex < 0 || attributeIndex > AttributeCount)
  460. throw new ArgumentOutOfRangeException ();
  461. state = ReadState.Interactive;
  462. current = ownerElement.Attributes [attributeIndex];
  463. }
  464. public override bool MoveToAttribute (string name)
  465. {
  466. if (entityReader != null) {
  467. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  468. return entityReader.MoveToAttribute (name);
  469. // And in case of abondoning entityReader, go on...
  470. }
  471. if (isEndElement || current == null)
  472. return false;
  473. XmlNode tmpCurrent = current;
  474. if (current.ParentNode.NodeType == XmlNodeType.Attribute)
  475. current = current.ParentNode;
  476. XmlAttribute attr = ownerElement.Attributes [name];
  477. if (attr == null) {
  478. current = tmpCurrent;
  479. return false;
  480. }
  481. else {
  482. current = attr;
  483. return true;
  484. }
  485. }
  486. public override bool MoveToAttribute (string name, string namespaceURI)
  487. {
  488. if (entityReader != null) {
  489. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  490. return entityReader.MoveToAttribute (name, namespaceURI);
  491. // And in case of abondoning entityReader, go on...
  492. }
  493. if (isEndElement || current == null)
  494. return false;
  495. XmlAttribute attr = ownerElement.Attributes [name, namespaceURI];
  496. if (attr == null)
  497. return false;
  498. else {
  499. current = attr;
  500. return true;
  501. }
  502. }
  503. private void MoveToParentElement ()
  504. {
  505. // This is buggy. It is not only the case when EndElement = true.
  506. isEndElement = true;
  507. depth--;
  508. current = current.ParentNode;
  509. }
  510. public override bool MoveToElement ()
  511. {
  512. if (entityReader != null) {
  513. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  514. return entityReader.MoveToElement ();
  515. // And in case of abondoning entityReader, go on...
  516. }
  517. if (current == null)
  518. return false;
  519. XmlNode n = ownerElement;
  520. if (current != n) {
  521. // if (current.NodeType == XmlNodeType.Attribute) {
  522. current = n;//((XmlAttribute) current).OwnerElement;
  523. return true;
  524. } else
  525. return false;
  526. }
  527. public override bool MoveToFirstAttribute ()
  528. {
  529. if (entityReader != null) {
  530. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  531. return entityReader.MoveToFirstAttribute ();
  532. // And in case of abondoning entityReader, go on...
  533. }
  534. if (current == null)
  535. return false;
  536. if(ownerElement.Attributes.Count > 0)
  537. {
  538. current = ownerElement.Attributes [0];
  539. return true;
  540. }
  541. else
  542. return false;
  543. }
  544. public override bool MoveToNextAttribute ()
  545. {
  546. if (entityReader != null) {
  547. if (!this.CheckAndResetEntityReaderOnMoveToAttribute ())
  548. return entityReader.MoveToNextAttribute ();
  549. // And in case of abondoning entityReader, go on...
  550. }
  551. if (current == null)
  552. return false;
  553. if (current.NodeType != XmlNodeType.Attribute)
  554. return MoveToFirstAttribute ();
  555. else
  556. {
  557. XmlAttributeCollection ac = ((XmlAttribute) current).OwnerElement.Attributes;
  558. for (int i=0; i<ac.Count-1; i++)
  559. {
  560. XmlAttribute attr = ac [i];
  561. if (attr == current)
  562. {
  563. i++;
  564. if (i == ac.Count)
  565. return false;
  566. current = ac [i];
  567. return true;
  568. }
  569. }
  570. return false;
  571. }
  572. }
  573. private bool MoveToNextSibling ()
  574. {
  575. if (nextIsEndElement) {
  576. // nextIsEndElement is set only by ReadString.
  577. nextIsEndElement = false;
  578. MoveToParentElement ();
  579. } else if (alreadyRead) {
  580. alreadyRead = false;
  581. return current != null;
  582. }
  583. if (current.NextSibling != null) {
  584. isEndElement = false;
  585. current = current.NextSibling;
  586. } else {
  587. MoveToParentElement ();
  588. }
  589. if (current == null) {
  590. state = ReadState.EndOfFile;
  591. return false;
  592. }
  593. else
  594. return true;
  595. }
  596. public override bool Read ()
  597. {
  598. if (EOF)
  599. return false;
  600. this.CheckAndResetEntityReaderOnMoveToAttribute ();
  601. if (entityReader != null) {
  602. // Read finalizes entity reader.
  603. switch (entityReader.ReadState) {
  604. case ReadState.Interactive:
  605. case ReadState.Initial:
  606. // If it is ended, then other properties/methods will take care.
  607. entityReader.Read ();
  608. return true;
  609. default:
  610. entityReader = entityReaderStack.Count > 0 ?
  611. entityReaderStack.Pop () as XmlTextReader : null;
  612. return Read ();
  613. }
  614. // and go on ...
  615. }
  616. if (ReadState == ReadState.Initial) {
  617. current = startNode;
  618. state = ReadState.Interactive;
  619. // when startNode is document or fragment
  620. if (!alreadyRead)
  621. current = startNode.FirstChild;
  622. else
  623. alreadyRead = false;
  624. if (current == null) {
  625. state = ReadState.Error;
  626. return false;
  627. } else
  628. return true;
  629. }
  630. MoveToElement ();
  631. if (IsEmptyElement || isEndElement) {
  632. // Then go up and move to next.
  633. // If no more nodes, then set EOF.
  634. isEndElement = false;
  635. if (current.ParentNode == null
  636. || current.ParentNode.NodeType == XmlNodeType.Document
  637. || current.ParentNode.NodeType == XmlNodeType.DocumentFragment) {
  638. current = null;
  639. state = ReadState.EndOfFile;
  640. return false;
  641. } else if (current.NextSibling == null) {
  642. depth--;
  643. current = current.ParentNode;
  644. isEndElement = true;
  645. return true;
  646. } else {
  647. current = current.NextSibling;
  648. return true;
  649. }
  650. } else if (nextIsEndElement) {
  651. // nextIsEndElement is set only by ReadString.
  652. nextIsEndElement = false;
  653. isEndElement = true;
  654. return current != null;
  655. } else if (alreadyRead) {
  656. alreadyRead = false;
  657. return current != null;
  658. }
  659. if (!isEndElement && current.FirstChild != null && current.NodeType != XmlNodeType.EntityReference) {
  660. isEndElement = false;
  661. current = current.FirstChild;
  662. depth++;
  663. } else if (current.NodeType == XmlNodeType.Element) {
  664. isEndElement = true;
  665. if (current.FirstChild != null)
  666. depth--;
  667. } else
  668. MoveToNextSibling ();
  669. return current != null;
  670. }
  671. public override bool ReadAttributeValue ()
  672. {
  673. if (entityReader != null) {
  674. switch (entityReader.ReadState) {
  675. case ReadState.Interactive:
  676. case ReadState.Initial:
  677. // If it is ended, then other properties/methods will take care.
  678. return entityReader.ReadAttributeValue ();
  679. default:
  680. entityReader = entityReaderStack.Count > 0 ?
  681. entityReaderStack.Pop () as XmlTextReader : null;
  682. // and go on ...
  683. return ReadAttributeValue ();
  684. }
  685. }
  686. if (current.NodeType == XmlNodeType.Attribute) {
  687. if (current.FirstChild == null)
  688. return false;
  689. current = current.FirstChild;
  690. return true;
  691. } else if (current.ParentNode.NodeType == XmlNodeType.Attribute) {
  692. if (current.NextSibling == null)
  693. return false;
  694. current = current.NextSibling;
  695. return true;
  696. } else
  697. return false;
  698. }
  699. #if NET_1_0
  700. // Its traversal behavior is almost same as Read().
  701. public override string ReadInnerXml ()
  702. {
  703. if (entityReader != null) {
  704. if (entityReader.EOF) {
  705. entityReader = entityReaderStack.Count > 0 ?
  706. entityReaderStack.Pop () as XmlTextReader : null;
  707. return ReadInnerXml ();
  708. } else
  709. return entityReader.ReadInnerXml ();
  710. }
  711. if (this.state != ReadState.Interactive)
  712. return String.Empty;
  713. XmlNode initial = current;
  714. // Almost copied from XmlTextReader.
  715. switch (NodeType) {
  716. case XmlNodeType.Attribute:
  717. return Value;
  718. case XmlNodeType.Element:
  719. if (IsEmptyElement)
  720. return String.Empty;
  721. int startDepth = depth;
  722. bool loop = true;
  723. do {
  724. Read ();
  725. if (NodeType ==XmlNodeType.None)
  726. throw new XmlException ("unexpected end of xml.");
  727. else if (NodeType == XmlNodeType.EndElement && depth == startDepth) {
  728. loop = false;
  729. Read ();
  730. }
  731. } while (loop);
  732. return initial.InnerXml;
  733. case XmlNodeType.None:
  734. return String.Empty;
  735. default:
  736. Read ();
  737. return String.Empty;
  738. }
  739. }
  740. // Its traversal behavior is almost same as Read().
  741. public override string ReadOuterXml ()
  742. {
  743. if (entityReader != null) {
  744. if (entityReader.EOF) {
  745. entityReader = entityReaderStack.Count > 0 ?
  746. entityReaderStack.Pop () as XmlTextReader : null;
  747. return ReadOuterXml ();
  748. } else
  749. return entityReader.ReadOuterXml ();
  750. }
  751. if (NodeType == XmlNodeType.EndElement)
  752. return String.Empty;
  753. XmlNode initial = current;
  754. switch (NodeType) {
  755. case XmlNodeType.Attribute:
  756. return current.OuterXml;
  757. case XmlNodeType.Element:
  758. if (NodeType == XmlNodeType.Element && !IsEmptyElement)
  759. ReadInnerXml ();
  760. else
  761. Read ();
  762. return initial.OuterXml;
  763. case XmlNodeType.None:
  764. return String.Empty;
  765. default:
  766. Read ();
  767. return String.Empty;
  768. }
  769. }
  770. #endif
  771. public override string ReadString ()
  772. {
  773. return ReadStringInternal ();
  774. }
  775. public override void ResolveEntity ()
  776. {
  777. if (NodeType != XmlNodeType.EntityReference)
  778. throw new InvalidOperationException ("The current node is not an Entity Reference");
  779. // FIXME: Now that XmlEntityReference holds the target
  780. // entity's child nodes, we don't have to use
  781. // XmlTextReader and simply use those nodes directly.
  782. string replacementText = current.InnerXml;
  783. XmlNodeType xmlReaderNodeType =
  784. (current.ParentNode != null && current.ParentNode.NodeType == XmlNodeType.Attribute) ?
  785. XmlNodeType.Attribute : XmlNodeType.Element;
  786. XmlParserContext ctx = null;
  787. if (entityReader != null) {
  788. entityReaderStack.Push (entityReader);
  789. ctx = entityReader.GetInternalParserContext ();
  790. }
  791. if (ctx == null) {
  792. ctx = new XmlParserContext (document.NameTable,
  793. current.ConstructNamespaceManager (),
  794. document.DocumentType != null ? document.DocumentType.DTD : null,
  795. BaseURI, XmlLang, XmlSpace, Encoding.Unicode);
  796. }
  797. entityReader = new XmlTextReader (replacementText, xmlReaderNodeType, ctx);
  798. entityReader.XmlResolver = document.Resolver;
  799. entityReader.SkipTextDeclaration ();
  800. }
  801. public override void Skip ()
  802. {
  803. // Why is this overriden? Such skipping might raise
  804. // (or ignore) unexpected validation error.
  805. base.Skip ();
  806. }
  807. #endregion
  808. }
  809. }