In System.Data.OleDb:
[mono.git] / mcs / class / System.Data / System.Data / XmlDataReader.cs
old mode 100755 (executable)
new mode 100644 (file)
index a9e867b..cef1ef4
@@ -1,4 +1,28 @@
-using System;\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
 using System.IO;\r
 using System.Data;\r
 using System.Xml;\r
@@ -80,49 +104,68 @@ namespace System.Data
 \r
                private void Process ()\r
                {\r
-                       // set EnforceConstraint to false during load time.\r
                        bool savedEnforceConstraints =\r
                                dataset.EnforceConstraints;\r
+                       try {\r
                        dataset.EnforceConstraints = false;\r
-\r
                        reader.MoveToContent ();\r
 \r
                        if (mode == XmlReadMode.Fragment) {\r
-                               do {\r
-                                       if (XmlConvert.DecodeName (reader.LocalName) == dataset.DataSetName && reader.NamespaceURI == dataset.Namespace)\r
+                                       while (reader.NodeType == XmlNodeType.Element && !reader.EOF) {\r
                                                ReadTopLevelElement ();\r
-                                       else\r
-                                               reader.Skip ();\r
-                               } while (!reader.EOF);\r
-                       } else {\r
-                               // Top level element can be ignored, being regarded \r
-                               // just as a wrapper (even it is not dataset element).\r
-                               DataTable tab = dataset.Tables [XmlConvert.DecodeName (reader.LocalName)];\r
-                               if (tab != null && tab.Namespace == reader.NamespaceURI)\r
-                                       ReadDataSetContent ();\r
+                                       }\r
+                               }\r
                                else\r
                                        ReadTopLevelElement ();\r
-                               reader.MoveToContent ();\r
+                       } finally {\r
+                               dataset.EnforceConstraints = \r
+                                       savedEnforceConstraints;\r
                        }\r
+               }\r
+\r
+               private bool IsTopLevelDataSet ()\r
+               {\r
+                       string local = XmlConvert.DecodeName (reader.LocalName);\r
 \r
-                       dataset.EnforceConstraints = savedEnforceConstraints;\r
+                       // No need to check DataSetName. In fact, it is ignored.\r
+\r
+                       bool ambiguous = false;\r
+                       DataTable dt = dataset.Tables [local];\r
+                       if (dt == null)\r
+                               return true;\r
+\r
+                       XmlDocument doc = new XmlDocument ();\r
+                       XmlElement el = (XmlElement) doc.ReadNode (reader);\r
+                       doc.AppendChild (el);\r
+                       reader = new XmlNodeReader (el);\r
+                       reader.MoveToContent ();\r
+\r
+                       return !XmlDataInferenceLoader.IsDocumentElementTable (\r
+                               el, null);\r
                }\r
 \r
                private void ReadTopLevelElement ()\r
                {\r
+                       if (mode == XmlReadMode.Fragment &&\r
+                               (XmlConvert.DecodeName (reader.LocalName) !=\r
+                               dataset.DataSetName ||\r
+                               reader.NamespaceURI != dataset.Namespace))\r
+                               reader.Skip ();\r
+                       else if (mode == XmlReadMode.Fragment ||\r
+                               IsTopLevelDataSet ()) {\r
                        int depth = reader.Depth;\r
                        reader.Read ();\r
                        reader.MoveToContent ();\r
                        do {\r
                                ReadDataSetContent ();\r
                        } while (reader.Depth > depth && !reader.EOF);\r
-\r
-                       if (reader.IsEmptyElement)\r
-                               reader.Read ();\r
                        if (reader.NodeType == XmlNodeType.EndElement)\r
                                reader.ReadEndElement ();\r
                        reader.MoveToContent ();\r
                }\r
+                       else\r
+                               ReadDataSetContent ();\r
+               }\r
 \r
                private void ReadDataSetContent ()\r
                {\r
@@ -134,8 +177,6 @@ namespace System.Data
                        }\r
 \r
                        // skip if namespace does not match.\r
-                       // TODO: This part is suspicious for MS compatibility\r
-                       // (test required)\r
                        if (table.Namespace != reader.NamespaceURI) {\r
                                reader.Skip ();\r
                                reader.MoveToContent ();\r
@@ -152,7 +193,7 @@ namespace System.Data
                        // Consume attributes\r
                        if (reader.MoveToFirstAttribute ()) {\r
                                do {\r
-                                       if (reader.NamespaceURI == xmlnsNS)\r
+                                       if (reader.NamespaceURI == XmlConstants.XmlnsNS)\r
                                                continue;\r
                                        ReadElementAttribute (row);\r
                                } while (reader.MoveToNextAttribute ());\r
@@ -183,7 +224,7 @@ namespace System.Data
                        DataColumn col = row.Table.Columns [XmlConvert.DecodeName (reader.LocalName)];\r
                        if (col == null || col.Namespace != reader.NamespaceURI)\r
                                return;\r
-                       row [col] = reader.Value;\r
+                       row [col] = StringToObject (col.DataType, reader.Value);\r
                }\r
 \r
                private void ReadElementContent (DataRow row)\r
@@ -216,8 +257,9 @@ namespace System.Data
 #if SILLY_MS_COMPATIBLE\r
 // As to MS, "test string" and "test <!-- comment -->string" are different :P\r
                                if (simple != null && row.IsNull (simple))\r
-                                       row [simple] = s;\r
+                                       row [simple] = StringToObject (simple.DataType, s);\r
 #else\r
+// But it does not mean we support "123<!-- comment -->456". just allowed for string\r
                                if (simple != null)\r
                                        row [simple] += s;\r
 #endif\r
@@ -258,7 +300,7 @@ namespace System.Data
 \r
                                bool wasEmpty = reader.IsEmptyElement;\r
                                int depth = reader.Depth;\r
-                               row [col] = reader.ReadElementString ();\r
+                               row [col] = StringToObject (col.DataType, reader.ReadElementString ());\r
                                if (!wasEmpty && reader.Depth > depth) {\r
                                // This means, instance does not match with\r
                                // the schema (because the instance element\r
@@ -303,5 +345,33 @@ namespace System.Data
                        reader.Skip ();\r
                        reader.MoveToContent ();\r
                }\r
+\r
+               internal static object StringToObject (Type type, string value)\r
+               {\r
+                       if (type == null) return value;\r
+\r
+                       switch (Type.GetTypeCode (type)) {\r
+                               case TypeCode.Boolean: return XmlConvert.ToBoolean (value);\r
+                               case TypeCode.Byte: return XmlConvert.ToByte (value);\r
+                               case TypeCode.Char: return (char)XmlConvert.ToInt32 (value);\r
+                               case TypeCode.DateTime: return XmlConvert.ToDateTime (value);\r
+                               case TypeCode.Decimal: return XmlConvert.ToDecimal (value);\r
+                               case TypeCode.Double: return XmlConvert.ToDouble (value);\r
+                               case TypeCode.Int16: return XmlConvert.ToInt16 (value);\r
+                               case TypeCode.Int32: return XmlConvert.ToInt32 (value);\r
+                               case TypeCode.Int64: return XmlConvert.ToInt64 (value);\r
+                               case TypeCode.SByte: return XmlConvert.ToSByte (value);\r
+                               case TypeCode.Single: return XmlConvert.ToSingle (value);\r
+                               case TypeCode.UInt16: return XmlConvert.ToUInt16 (value);\r
+                               case TypeCode.UInt32: return XmlConvert.ToUInt32 (value);\r
+                               case TypeCode.UInt64: return XmlConvert.ToUInt64 (value);\r
+                       }\r
+\r
+                       if (type == typeof (TimeSpan)) return XmlConvert.ToTimeSpan (value);\r
+                       if (type == typeof (Guid)) return XmlConvert.ToGuid (value);\r
+                       if (type == typeof (byte[])) return Convert.FromBase64String (value);\r
+\r
+                       return Convert.ChangeType (value, type);\r
+               }\r
        }\r
 }\r