2 // Patrick Earl <mono@patearl.net>
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Text.RegularExpressions;
31 using NUnit.Framework;
33 namespace MonoTests.System.Data
36 public class DataTableReadWriteXmlTest
39 void StandardizeXmlFormat(ref string xml)
41 XmlDocument doc = new XmlDocument();
43 StringWriter sw = new StringWriter();
48 void GenerateTestData(out DataSet ds,
49 out DataTable dtMainInDS,
50 out DataTable dtChildInDS,
53 ds = new DataSet("MyDataSet");
55 // Create a primary table and populate it with some data. Make a
56 // copy of the primary table and put it into the dataset.
57 dtMain = new DataTable("Main");
58 dtMain.Columns.Add(new DataColumn("ID", typeof(int)));
59 dtMain.Columns.Add(new DataColumn("Data", typeof(string)));
61 DataRow row = dtMain.NewRow();
66 row = dtMain.NewRow();
71 row = dtMain.NewRow();
73 row["Data"] = "Three";
76 dtMainInDS = dtMain.Copy();
77 ds.Tables.Add(dtMainInDS);
79 // Create a child table. Make a copy of the child table and put
80 // it into the dataset.
81 dtChildInDS = new DataTable("Child");
82 dtChildInDS.Columns.Add(new DataColumn("ID", typeof(int)));
83 dtChildInDS.Columns.Add(new DataColumn("PID", typeof(int)));
84 dtChildInDS.Columns.Add(new DataColumn("ChildData", typeof(string)));
86 row = dtChildInDS.NewRow();
89 row["ChildData"] = "Parent1Child1";
90 dtChildInDS.Rows.Add(row);
92 row = dtChildInDS.NewRow();
95 row["ChildData"] = "Parent1Child2";
96 dtChildInDS.Rows.Add(row);
98 row = dtChildInDS.NewRow();
101 row["ChildData"] = "Parent2Child3";
102 dtChildInDS.Rows.Add(row);
104 ds.Tables.Add(dtChildInDS);
106 // Set up the relation in the dataset.
107 ds.Relations.Add(new DataRelation("MainToChild",
108 dtMainInDS.Columns["ID"],
109 dtChildInDS.Columns["PID"]));
113 public void TestWriteXml()
116 DataTable dtMainInDS, dtChildInDS, dtMain;
118 GenerateTestData(out ds,
123 StringWriter sw = new StringWriter();
125 // Get XML for DataSet writes.
126 sw.GetStringBuilder().Length = 0;
128 string xmlDSNone = sw.ToString();
130 sw.GetStringBuilder().Length = 0;
131 ds.WriteXml(sw, XmlWriteMode.DiffGram);
132 string xmlDSDiffGram = sw.ToString();
134 sw.GetStringBuilder().Length = 0;
135 ds.WriteXml(sw, XmlWriteMode.WriteSchema);
136 string xmlDSWriteSchema = sw.ToString();
138 // Get XML for recursive DataTable writes of the same data as in
140 sw.GetStringBuilder().Length = 0;
141 dtMainInDS.WriteXml(sw, true);
142 string xmlDTNone = sw.ToString();
144 sw.GetStringBuilder().Length = 0;
145 dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
146 string xmlDTDiffGram = sw.ToString();
148 sw.GetStringBuilder().Length = 0;
149 dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
150 string xmlDTWriteSchema = sw.ToString();
152 // The schema XML written by the DataTable call has an extra element
153 // in the element for the dataset schema definition. We remove that
154 // extra attribute and then check to see if the rest of the xml is
156 XmlDocument doc = new XmlDocument();
157 doc.LoadXml(xmlDTWriteSchema);
158 XmlNode node = doc.DocumentElement.FirstChild.FirstChild;
159 XmlAttribute a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
160 Assert.IsNotNull(a, "Test#01");
161 Assert.AreEqual("Main", a.Value, "Test#02");
163 node.Attributes.Remove(a);
164 sw.GetStringBuilder().Length = 0;
166 xmlDTWriteSchema = sw.ToString();
168 StandardizeXmlFormat(ref xmlDSWriteSchema);
170 Assert.AreEqual(xmlDSNone, xmlDTNone, "Test#03");
171 Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGram, "Test#04");
172 Assert.IsTrue (xmlDSWriteSchema.IndexOf ("UseCurrentLocale") > 0, "Test#05-premise1");
173 Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchema, "Test#05");
175 // Now that we've tested writing tables (including children),
176 // we will go on to test the cases where the hierarchy flag
177 // is false. For this, we will test one table inside the
178 // dataset and one table outside the dataset.
180 // First, we fix our test DataSet to only have a single table
181 // with no relations. Then, we go about comparing the XML.
182 // Get XML for DataSet writes.
183 ds.Tables[1].Constraints.Remove(ds.Tables[1].Constraints[0]);
184 ds.Tables[0].Constraints.Remove(ds.Tables[0].Constraints[0]);
185 ds.Tables[0].ChildRelations.Remove("MainToChild");
186 ds.Tables.Remove("Child");
188 sw.GetStringBuilder().Length = 0;
190 xmlDSNone = sw.ToString();
192 sw.GetStringBuilder().Length = 0;
193 ds.WriteXml(sw, XmlWriteMode.DiffGram);
194 xmlDSDiffGram = sw.ToString();
196 sw.GetStringBuilder().Length = 0;
197 ds.WriteXml(sw, XmlWriteMode.WriteSchema);
198 xmlDSWriteSchema = sw.ToString();
200 // Get all the DataTable.WriteXml results.
201 sw.GetStringBuilder().Length = 0;
202 dtMainInDS.WriteXml(sw);
203 string xmlDTNoneInDS = sw.ToString();
205 sw.GetStringBuilder().Length = 0;
206 dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram);
207 string xmlDTDiffGramInDS = sw.ToString();
209 sw.GetStringBuilder().Length = 0;
210 dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema);
211 string xmlDTWriteSchemaInDS = sw.ToString();
213 sw.GetStringBuilder().Length = 0;
215 string xmlDTNoneNoDS = sw.ToString();
217 sw.GetStringBuilder().Length = 0;
218 dtMain.WriteXml(sw, XmlWriteMode.DiffGram);
219 string xmlDTDiffGramNoDS = sw.ToString();
221 sw.GetStringBuilder().Length = 0;
222 dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
223 string xmlDTWriteSchemaNoDS = sw.ToString();
225 Assert.AreEqual(xmlDSNone, xmlDTNoneInDS, "Test#06");
227 // The only difference between the xml output from inside the
228 // dataset and the xml output from outside the dataset is that
229 // there's a fake <DocumentElement> tag surrounding tbe table
230 // in the second case. We replace it with the name of the
231 // dataset for testing purposes.
232 doc.LoadXml(xmlDTNoneNoDS);
233 Assert.AreEqual("DocumentElement", doc.DocumentElement.Name, "Test#07");
234 sw.GetStringBuilder().Length = 0;
236 xmlDTNoneNoDS = sw.ToString();
237 xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("<DocumentElement>", "<MyDataSet>");
238 xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("</DocumentElement>", "</MyDataSet>");
240 StandardizeXmlFormat(ref xmlDSNone);
242 Assert.AreEqual(xmlDSNone, xmlDTNoneNoDS, "Test#08");
244 // Now check the DiffGram.
245 Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramInDS, "Test#09");
247 doc.LoadXml(xmlDTDiffGramNoDS);
248 Assert.AreEqual("DocumentElement", doc.DocumentElement.FirstChild.Name, "Test#10");
249 xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("<DocumentElement>", "<MyDataSet>");
250 xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("</DocumentElement>", "</MyDataSet>");
252 Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramNoDS, "Test#11");
254 // Finally we check the WriteSchema version of the data. First
255 // we remove the extra "msdata:MainDataTable" attribute from
256 // the schema declaration part of the DataTable xml.
257 doc = new XmlDocument();
258 doc.LoadXml(xmlDTWriteSchemaInDS);
259 node = doc.DocumentElement.FirstChild.FirstChild;
260 a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
261 Assert.IsNotNull(a, "Test#12");
262 Assert.AreEqual("Main", a.Value, "Test#13");
263 node.Attributes.Remove(a);
264 sw.GetStringBuilder().Length = 0;
266 xmlDTWriteSchemaInDS = sw.ToString();
268 StandardizeXmlFormat(ref xmlDSWriteSchema);
270 Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaInDS, "Test#14");
272 // Remove the extra "msdata:MainDataTable" for the other test case.
273 // Also make sure we have "NewDataSet" in the appropriate locations.
274 doc = new XmlDocument();
275 doc.LoadXml(xmlDTWriteSchemaNoDS);
276 node = doc.DocumentElement.FirstChild.FirstChild;
277 a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
278 Assert.IsNotNull(a, "Test#15");
279 Assert.AreEqual("Main", a.Value, "Test#16");
280 node.Attributes.Remove(a);
281 sw.GetStringBuilder().Length = 0;
284 Assert.AreEqual("NewDataSet", doc.DocumentElement.Name, "Test#17");
285 Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.Attributes["id"].Value, "Test#18");
286 Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.FirstChild.Attributes["name"].Value, "Test#19");
288 xmlDTWriteSchemaNoDS = sw.ToString();
290 xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("<NewDataSet>","<MyDataSet>");
291 xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("</NewDataSet>","</MyDataSet>");
292 xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("\"NewDataSet\"","\"MyDataSet\"");
294 Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaNoDS, "Test#20");
298 public void TestReadXml()
300 // For reading, DataTable.ReadXml only supports reading in xml with
301 // the schema included. This means that we can only read in XML
302 // that was generated with the WriteSchema flag.
304 DataTable dtMainInDS, dtChildInDS, dtMain;
306 GenerateTestData(out ds,
311 StringWriter sw = new StringWriter();
313 // Get XML for recursive DataTable writes of the same data as in
315 sw.GetStringBuilder().Length = 0;
316 dtMainInDS.WriteXml(sw, true);
317 string xmlDTNone = sw.ToString();
319 sw.GetStringBuilder().Length = 0;
320 dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
321 string xmlDTDiffGram = sw.ToString();
323 sw.GetStringBuilder().Length = 0;
324 dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
325 string xmlMultiTable = sw.ToString();
327 sw.GetStringBuilder().Length = 0;
328 dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
329 string xmlSingleTable = sw.ToString();
331 DataTable newdt = new DataTable();
334 newdt.ReadXml(new StringReader(xmlDTNone));
335 Assert.Fail("Test#01");
336 } catch(InvalidOperationException) {
337 // DataTable does not support schema inference from Xml.
341 newdt.ReadXml(new StringReader(xmlDTDiffGram));
342 Assert.Fail("Test#02");
343 } catch(InvalidOperationException) {
344 // DataTable does not support schema inference from Xml.
347 DataTable multiTable = new DataTable();
348 multiTable.ReadXml(new StringReader(xmlMultiTable));
349 // Do some simple checks to see if the main dataset was created
350 // and if there are relationships present.
351 Assert.AreEqual("MyDataSet", multiTable.DataSet.DataSetName, "Test#03");
352 Assert.AreEqual(1, multiTable.ChildRelations.Count, "Test#04");
353 Assert.AreEqual(1, multiTable.Constraints.Count, "Test#05");
354 // Write the table back out and check to see that the XML is
355 // the same as before.
356 sw.GetStringBuilder().Length = 0;
357 multiTable.WriteXml(sw, XmlWriteMode.WriteSchema, true);
358 string xmlMultiTableCheck = sw.ToString();
359 Assert.IsTrue (xmlMultiTable.IndexOf ("UseCurrentLocale") > 0, "Test#06-premise1");
360 Assert.IsTrue (xmlMultiTable.IndexOf ("keyref") > 0, "Test#06-premise2");
361 Assert.AreEqual(xmlMultiTable, xmlMultiTableCheck, "Test#06");
363 DataTable singleTable = new DataTable();
364 singleTable.ReadXml(new StringReader(xmlSingleTable));
365 // Do some simple checks on the table.
366 Assert.IsNull(singleTable.DataSet, "Test#07");
367 Assert.AreEqual("Main", singleTable.TableName, "Test#08");
368 // Write the table out and check if it's the same.
369 sw.GetStringBuilder().Length = 0;
370 singleTable.WriteXml(sw, XmlWriteMode.WriteSchema);
371 string xmlSingleTableCheck = sw.ToString();
372 Assert.AreEqual(xmlSingleTable, xmlSingleTableCheck, "Test#09");