XmlDataDocument.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. //
  2. // mcs/class/System.Data/System.Xml/XmlDataDocument.cs
  3. //
  4. // Purpose: Provides a W3C XML DOM Document to interact with
  5. // relational data in a DataSet
  6. //
  7. // class: XmlDataDocument
  8. // assembly: System.Data.dll
  9. // namespace: System.Xml
  10. //
  11. // Author:
  12. // Daniel Morgan <[email protected]>
  13. // Ville Palo <[email protected]>
  14. //
  15. // (c)copyright 2002 Daniel Morgan
  16. //
  17. // XmlDataDocument is included within the Mono Class Library.
  18. //
  19. using System;
  20. using System.Data;
  21. using System.IO;
  22. using System.Text;
  23. using System.Xml.XPath;
  24. using System.Collections;
  25. namespace System.Xml {
  26. public class XmlDataDocument : XmlDocument {
  27. #region Fields
  28. private DataSet dataSet;
  29. private bool isReadOnly = false;
  30. private int dataRowID = 1;
  31. private ArrayList dataRowIDList = new ArrayList ();
  32. #endregion // Fields
  33. #region Constructors
  34. public XmlDataDocument() {
  35. dataSet = new DataSet();
  36. }
  37. public XmlDataDocument(DataSet dataset) {
  38. this.dataSet = dataset;
  39. }
  40. #endregion // Constructors
  41. #region Public Properties
  42. public override string BaseURI {
  43. [MonoTODO]
  44. get {
  45. // TODO: why are we overriding?
  46. return base.BaseURI;
  47. }
  48. }
  49. public DataSet DataSet {
  50. [MonoTODO]
  51. get {
  52. return dataSet;
  53. }
  54. }
  55. // override inheritted method from XmlDocument
  56. public override string InnerXml {
  57. [MonoTODO]
  58. get {
  59. throw new NotImplementedException();
  60. }
  61. [MonoTODO]
  62. set {
  63. throw new NotImplementedException();
  64. }
  65. }
  66. public override bool IsReadOnly {
  67. [MonoTODO]
  68. get {
  69. return isReadOnly;
  70. }
  71. }
  72. // Item indexer
  73. public override XmlElement this[string name] {
  74. [MonoTODO]
  75. get {
  76. throw new NotImplementedException();
  77. }
  78. }
  79. // Item indexer
  80. public override XmlElement this[string localname, string ns] {
  81. [MonoTODO]
  82. get {
  83. throw new NotImplementedException();
  84. }
  85. }
  86. public override string LocalName {
  87. [MonoTODO]
  88. get {
  89. throw new NotImplementedException();
  90. }
  91. }
  92. public override string Name {
  93. [MonoTODO]
  94. get {
  95. throw new NotImplementedException();
  96. }
  97. }
  98. public override XmlDocument OwnerDocument {
  99. [MonoTODO]
  100. get {
  101. return null;
  102. }
  103. }
  104. #endregion // Public Properties
  105. #region Public Methods
  106. [MonoTODO]
  107. public override XmlNode CloneNode(bool deep)
  108. {
  109. throw new NotImplementedException();
  110. }
  111. #region overloaded CreateElement methods
  112. [MonoTODO]
  113. public override XmlElement CreateElement(string prefix,
  114. string localName, string namespaceURI)
  115. {
  116. if ((localName == null) || (localName == String.Empty))
  117. throw new ArgumentException ("The local name for elements or attributes cannot be null" +
  118. "or an empty string.");
  119. string pref = prefix != null ? prefix : String.Empty;
  120. return base.CreateElement (pref, localName, namespaceURI != null ? namespaceURI : String.Empty);
  121. }
  122. #endregion // overloaded CreateElement Methods
  123. // will not be supported
  124. public override XmlEntityReference CreateEntityReference(string name)
  125. {
  126. throw new NotSupportedException();
  127. }
  128. // will not be supported
  129. public override XmlElement GetElementById(string elemId)
  130. {
  131. throw new NotSupportedException();
  132. }
  133. // get the XmlElement associated with the DataRow
  134. public XmlElement GetElementFromRow(DataRow r)
  135. {
  136. throw new NotImplementedException();
  137. }
  138. // get the DataRow associated with the XmlElement
  139. [MonoTODO]
  140. public DataRow GetRowFromElement(XmlElement e)
  141. {
  142. throw new NotImplementedException();
  143. }
  144. #region overload Load methods
  145. public override void Load(Stream inStream) {
  146. Load (new XmlTextReader (inStream));
  147. }
  148. public override void Load(string filename) {
  149. Load (new XmlTextReader (filename));
  150. }
  151. public override void Load(TextReader txtReader) {
  152. Load (new XmlTextReader (txtReader));
  153. }
  154. public override void Load(XmlReader reader) {
  155. DataTable dt = null;
  156. // For reading xml to XmlDocument
  157. XmlTextReader textReader = new XmlTextReader (
  158. reader.BaseURI);
  159. if (reader.NodeType != XmlNodeType.Element)
  160. reader.MoveToContent ();
  161. // TODO: Findout which exception should be throwen
  162. if (reader.NodeType != XmlNodeType.Element)
  163. throw new Exception ();
  164. if (dataSet.DataSetName != reader.Name)
  165. throw new Exception ();
  166. // read to next element
  167. while (reader.Read () && reader.NodeType != XmlNodeType.Element);
  168. do {
  169. // Find right table from tablecollection
  170. for (int i = 0; i < DataSet.Tables.Count && dt == null; i++) {
  171. if (reader.Name == DataSet.Tables [i].TableName) {
  172. dt = DataSet.Tables [i];
  173. dt.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
  174. dt.RowDeleted += new DataRowChangeEventHandler (OnDataTableRowDeleted);
  175. dt.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
  176. }
  177. }
  178. // TODO: Findout what kind of exception
  179. if (dt == null)
  180. throw new Exception (); // there were no correct table
  181. // Read rows to table
  182. DataRow tempRow = dt.NewRow ();
  183. while ((reader.NodeType != XmlNodeType.EndElement ||
  184. reader.Name != dt.TableName) && reader.Read()) {
  185. switch (reader.NodeType) {
  186. case XmlNodeType.Element:
  187. // Add column to DataRow
  188. LoadRow (reader, ref tempRow);
  189. break;
  190. default:
  191. break;
  192. }
  193. }
  194. // Every row must have unique id.
  195. tempRow.XmlRowID = dataRowID;
  196. dataRowIDList.Add (dataRowID);
  197. dt.Rows.Add (tempRow);
  198. dataRowID++;
  199. } while (reader.Read ());
  200. base.Load (textReader);
  201. }
  202. #endregion // overloaded Load methods
  203. [MonoTODO]
  204. public override void WriteContentTo(XmlWriter xw) {
  205. base.WriteContentTo (xw);
  206. }
  207. [MonoTODO]
  208. public override void WriteTo(XmlWriter w) {
  209. base.WriteTo (w);
  210. }
  211. #endregion // Public Methods
  212. #region Protected Methods
  213. //FIXME: how do you handle this?
  214. //[MonoTODO]
  215. //protected internal override XPathNavigator CreateNavigator(XmlNode node) {
  216. // throw new NotImplementedException();
  217. //}
  218. [MonoTODO]
  219. public new XPathNavigator CreateNavigator() {
  220. throw new NotImplementedException();
  221. }
  222. #endregion // Protected Methods
  223. #region DataSet event handlers
  224. [MonoTODO]
  225. private void OnDataTableColumnChanged(object sender,
  226. DataColumnChangeEventArgs eventArgs)
  227. {
  228. // row is not yet in datatable
  229. if (eventArgs.Row.XmlRowID == 0)
  230. return;
  231. // TODO: Here should be some kind of error checking.
  232. GetElementsByTagName (eventArgs.Column.ToString ()) [dataRowIDList.IndexOf (
  233. eventArgs.Row.XmlRowID)].InnerText = (string)eventArgs.ProposedValue;
  234. }
  235. [MonoTODO]
  236. private void OnDataTableRowDeleted(object sender,
  237. DataRowChangeEventArgs eventArgs)
  238. {
  239. DataRow deletedRow = null;
  240. deletedRow = eventArgs.Row;
  241. if (eventArgs.Row.XmlRowID == 0)
  242. return;
  243. int rowIndex = dataRowIDList.IndexOf (eventArgs.Row.XmlRowID);
  244. // Remove element from xmldocument and row indexlist
  245. GetElementsByTagName (deletedRow.Table.TableName) [rowIndex].RemoveAll ();
  246. dataRowIDList.RemoveAt (rowIndex);
  247. }
  248. [MonoTODO]
  249. private void OnDataTableRowChanged(object sender, DataRowChangeEventArgs eventArgs)
  250. {
  251. switch (eventArgs.Action) {
  252. case DataRowAction.Delete:
  253. OnDataTableRowDeleted (sender, eventArgs);
  254. break;
  255. case DataRowAction.Add:
  256. OnDataTableRowAdded (eventArgs);
  257. break;
  258. case DataRowAction.Rollback:
  259. OnDataTableRowRollback (eventArgs);
  260. break;
  261. default:
  262. break;
  263. }
  264. }
  265. // Added
  266. [MonoTODO]
  267. private void OnDataTableRowAdded (DataRowChangeEventArgs args)
  268. {
  269. // If XmlRowID is != 0 then it is already added
  270. if (args.Row.XmlRowID != 0)
  271. return;
  272. // Create row element. Row's name same as TableName
  273. DataRow row = args.Row;
  274. row.XmlRowID = dataRowID;
  275. dataRowID++;
  276. XmlElement element = CreateElement (args.Row.Table.TableName);
  277. DocumentElement.AppendChild (element);
  278. XmlElement rowElement = null;
  279. for (int i = 0; i < row.Table.Columns.Count; i++) {
  280. rowElement = CreateElement (row.Table.Columns [i].ToString ());
  281. rowElement.InnerText = (string)row [i];
  282. element.AppendChild (rowElement);
  283. }
  284. }
  285. // Rollback
  286. [MonoTODO]
  287. private void OnDataTableRowRollback (DataRowChangeEventArgs args)
  288. {
  289. DataRow row = args.Row;
  290. int rowid = dataRowIDList.IndexOf (row.XmlRowID);
  291. // find right element in xmldocument
  292. XmlNode node = GetElementsByTagName (row.Table.TableName) [rowid];
  293. int rowValue = 0;
  294. for (int i = 0; i < node.ChildNodes.Count; i++) {
  295. XmlNode child = node.ChildNodes [i];
  296. if (child.NodeType != XmlNodeType.Whitespace)
  297. child.InnerText = (string)row [rowValue++];
  298. }
  299. }
  300. #endregion // DataSet event handlers
  301. #region Private methods
  302. [MonoTODO]
  303. private void LoadRow (XmlReader reader, ref DataRow row)
  304. {
  305. // dt.Rows.Add (LoadRow (reader, dt.NewRow ()));
  306. // This method returns DataRow filled by values
  307. // from xmldocument
  308. string rowname = reader.Name;
  309. string column = "";
  310. if (reader.NodeType == XmlNodeType.Element)
  311. column = reader.Name;
  312. reader.Read ();
  313. if (reader.NodeType == XmlNodeType.Text) {
  314. string val = reader.Value;
  315. if (row.Table.Columns.Contains (column))
  316. row [column] = val;
  317. }
  318. }
  319. #endregion // Private methods
  320. }
  321. }