XmlDataReader.cs :  » 2.6.4-mono-.net-core » System.Data » System » Data » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Data 
System.Data » System » Data » XmlDataReader.cs

//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.Serialization;


namespace System.Data{
#if STANDALONE_DRIVER_TEST
  public class Driver
  {
    public static void Main (string [] args)
    {
      if (args.Length == 0) {
        Console.WriteLine ("usage: mono xmldatareader.exe filename");
        return;
      }

      Console.WriteLine ("Target file: " + args [0]);

      DataSet ds = new DataSet ();
//      ds.InferXmlSchema (args [0], null);

      try {
        ds.ReadXml (args [0]);
      } catch (Exception ex) {
        Console.WriteLine ("ReadXml() borked: " + ex.Message);
        return;
      }
      Console.WriteLine ("---- DataSet ----------------");
      StringWriter sw = new StringWriter ();
      PrintDataSet (ds, sw);
      PrintDataSet (ds, Console.Out);

      ds = new DataSet ();
      ds.InferXmlSchema (args [0], null);
      XmlDataReader.ReadXml (ds, new XmlTextReader (args [0]));
      Console.WriteLine ("---- XmlDataReader ----------------");
      StringWriter sw2 = new StringWriter ();
      PrintDataSet (ds, sw2);

      if (sw.ToString () == sw2.ToString ())
        Console.WriteLine ("Successful.");
      else
        Console.WriteLine ("Different *************************************************\n" + sw2);
    }

    private static void PrintDataSet (DataSet ds, TextWriter tw)
    {
      tw.WriteLine ("DS::" + ds.DataSetName + ", " + ds.Tables.Count + ", " + ds.Relations.Count);
      foreach (DataTable dt in ds.Tables)
        tw.WriteLine ("DT:" + dt.TableName + ", " + dt.Columns.Count + ", " + dt.Rows.Count);

      ds.WriteXml (tw);
      tw.WriteLine ();
    }
  }
#endif

  internal class XmlDataReader
  {
    const string xmlnsNS = "http://www.w3.org/2000/xmlns/";

    public static void ReadXml (
      DataSet dataset, XmlReader reader, XmlReadMode mode)
    {
      new XmlDataReader (dataset, reader, mode).Process ();
    }

    DataSet dataset;
    XmlReader reader;
    XmlReadMode mode;

    public XmlDataReader (DataSet ds, XmlReader xr, XmlReadMode m)
    {
      dataset = ds;
      reader =xr;
      mode = m;
    }

    private void Process ()
    {
      bool savedEnforceConstraints =
        dataset.EnforceConstraints;
      try {
      dataset.EnforceConstraints = false;
      reader.MoveToContent ();

      if (mode == XmlReadMode.Fragment) {
          while (reader.NodeType == XmlNodeType.Element && !reader.EOF) {
            ReadTopLevelElement ();
          }
        }
        else
          ReadTopLevelElement ();
      } finally {
        dataset.EnforceConstraints = 
          savedEnforceConstraints;
      }
    }

    private bool IsTopLevelDataSet ()
    {
      string local = XmlHelper.Decode (reader.LocalName);

      // No need to check DataSetName. In fact, it is ignored.

      DataTable dt = dataset.Tables [local];
      if (dt == null)
        return true;

      XmlDocument doc = new XmlDocument ();
      XmlElement el = (XmlElement) doc.ReadNode (reader);
      doc.AppendChild (el);
      reader = new XmlNodeReader (el);
      reader.MoveToContent ();

      return !XmlDataInferenceLoader.IsDocumentElementTable (
        el, null);
    }

    private void ReadTopLevelElement ()
    {
      if (mode == XmlReadMode.Fragment &&
        (XmlHelper.Decode (reader.LocalName) !=
        dataset.DataSetName ||
        reader.NamespaceURI != dataset.Namespace))
        reader.Skip ();
      else if (mode == XmlReadMode.Fragment ||
        IsTopLevelDataSet ()) {
      int depth = reader.Depth;
      reader.Read ();
      reader.MoveToContent ();
      do {
        ReadDataSetContent ();
      } while (reader.Depth > depth && !reader.EOF);
      if (reader.NodeType == XmlNodeType.EndElement)
        reader.ReadEndElement ();
      reader.MoveToContent ();
    }
      else
        ReadDataSetContent ();
    }

    private void ReadDataSetContent ()
    {
      DataTable table = dataset.Tables [XmlHelper.Decode (reader.LocalName)];
      if (table == null || table.Namespace != reader.NamespaceURI) {
        reader.Skip ();
        reader.MoveToContent ();
        return; // skip if there is no matching table
      }

      // skip if namespace does not match.
      if (table.Namespace != reader.NamespaceURI) {
        reader.Skip ();
        reader.MoveToContent ();
        return; // skip if there is no matching table
      }

      DataRow row = table.NewRow ();
      ReadElement (row);
      table.Rows.Add (row);
    }

    private void ReadElement (DataRow row)
    {
      // Consume attributes
      if (reader.MoveToFirstAttribute ()) {
        do {
          if (reader.NamespaceURI == XmlConstants.XmlnsNS
#if NET_2_0
          || reader.NamespaceURI == XmlConstants.XmlNS
#endif
            )
            continue;
          ReadElementAttribute (row);
        } while (reader.MoveToNextAttribute ());
        reader.MoveToElement ();
      }

      // If not empty element, read content.
      if (reader.IsEmptyElement) {
        reader.Skip ();
        reader.MoveToContent ();
      } else {
        int depth = reader.Depth;
        reader.Read ();
        reader.MoveToContent ();
        do {
          ReadElementContent (row);
        } while (reader.Depth > depth && !reader.EOF);
        if (reader.IsEmptyElement)
          reader.Read ();
        if (reader.NodeType == XmlNodeType.EndElement)
          reader.ReadEndElement ();
        reader.MoveToContent ();
      }
    }

    private void ReadElementAttribute (DataRow row)
    {
      DataColumn col = row.Table.Columns [XmlHelper.Decode (reader.LocalName)];
      if (col == null || col.Namespace != reader.NamespaceURI)
        return;
      row [col] = StringToObject (col.DataType, reader.Value);
    }

    private void ReadElementContent (DataRow row)
    {
      switch (reader.NodeType) {

      case XmlNodeType.EndElement:
        // This happens when the content was only whitespace (and skipped by MoveToContent()).
        return;

      case XmlNodeType.Element:
        ReadElementElement (row);
        break;

      case XmlNodeType.Text:
      case XmlNodeType.CDATA:
      case XmlNodeType.SignificantWhitespace:
        DataColumn simple = null;
        DataColumnCollection cols = row.Table.Columns;
        for (int i = 0; i < cols.Count; i++) {
          DataColumn col = cols [i];
          if (col.ColumnMapping ==
            MappingType.SimpleContent) {
            simple = col;
            break;
          }
        }
        string s = reader.ReadString ();
        reader.MoveToContent ();
#if SILLY_MS_COMPATIBLE
// As to MS, "test string" and "test <!-- comment -->string" are different :P
        if (simple != null && row.IsNull (simple))
          row [simple] = StringToObject (simple.DataType, s);
#else
// But it does not mean we support "123<!-- comment -->456". just allowed for string
        if (simple != null)
          row [simple] += s;
#endif
        break;
      case XmlNodeType.Whitespace:
        reader.ReadString ();
        break;
      }
    }

    private void ReadElementElement (DataRow row)
    {
      // This child element (for row) might be either simple
      // content element, or child element

      // MS.NET crashes here... but it seems just a bug.
      DataColumn col = row.Table.Columns [XmlHelper.Decode (reader.LocalName)];
      if (col == null ||  col.Namespace != reader.NamespaceURI)
        col = null;

      // if col exists, then it should be MappingType.Element
      if (col != null
        && col.ColumnMapping == MappingType.Element) {

        // TODO: This part is suspicious for
        // MS compatibility (test required)
        if (col.Namespace != reader.NamespaceURI) {
          reader.Skip ();
          return;
        }

        bool wasEmpty = reader.IsEmptyElement;
        int depth = reader.Depth;

        if (typeof (IXmlSerializable).IsAssignableFrom (col.DataType)) {
#if NET_2_0
          try {
            // NOTE: ReadElementString works fine with proper XML with CDATA etc,
            // however doesn't behave well with XMLs like the one in 
            // https://bugzilla.novell.com/show_bug.cgi?id=377146 which is 
            // apparently supported by MS.NET - to maintain compatibility,
            // If the obj implements IXmlSerializable, let obj's ReadXml do the reading
            IXmlSerializable obj = (IXmlSerializable) Activator.CreateInstance (col.DataType, new object [0]);
            if (!reader.IsEmptyElement) {
              obj.ReadXml (reader);
                 reader.ReadEndElement ();
            } else {
                 reader.Skip ();
            }            
            row [col] = obj;
          } catch (XmlException e) {
#endif
            // XML is not in accordance to expected standards, try reading the content as an xml doc
            row [col] = reader.ReadInnerXml ();
#if NET_2_0
          } catch (InvalidOperationException e) {

            row [col] = reader.ReadInnerXml ();
          }
#endif
        } else {
          row [col] = StringToObject (col.DataType, reader.ReadElementString ());
        }
          
        if (!wasEmpty && reader.Depth > depth) {
        // This means, instance does not match with
        // the schema (because the instance element
        // contains complex content, while specified as
        // simple), so just skip to the end of the
        // element.
          while (reader.Depth > depth)
            reader.Read ();
          reader.Read ();
        }
        reader.MoveToContent ();
        return;
      } else if (col != null) {
        // Mismatch column type. Just skip
        reader.Skip ();
        reader.MoveToContent ();
        return;
      }

      // Otherwise, it might be child table element
      DataRelationCollection rels = row.Table.ChildRelations;
      for (int i = 0; i < rels.Count; i++) {
        DataRelation rel = rels [i];
        if (!rel.Nested)
          continue;
        DataTable ct = rel.ChildTable;
        if (ct.TableName != XmlHelper.Decode (reader.LocalName) || ct.Namespace != reader.NamespaceURI)
          continue;

        DataRow childRow = rel.ChildTable.NewRow ();
        ReadElement (childRow);

        for (int c = 0; c < rel.ChildColumns.Length; c++) {
          childRow [rel.ChildColumns [c]]
            = row [rel.ParentColumns [c]];
        }
        rel.ChildTable.Rows.Add (childRow);
        return;
      }

      // Matched neither of the above: just skip
      reader.Skip ();
      reader.MoveToContent ();
    }

    internal static object StringToObject (Type type, string value)
    {
      if (type == null) return value;

      switch (Type.GetTypeCode (type)) {
        case TypeCode.Boolean: return XmlConvert.ToBoolean (value);
        case TypeCode.Byte: return XmlConvert.ToByte (value);
        case TypeCode.Char: return (char)XmlConvert.ToInt32 (value);
#if NET_2_0
        case TypeCode.DateTime: return XmlConvert.ToDateTime (value, XmlDateTimeSerializationMode.Unspecified);
#else
        case TypeCode.DateTime: return XmlConvert.ToDateTime (value);
#endif
        case TypeCode.Decimal: return XmlConvert.ToDecimal (value);
        case TypeCode.Double: return XmlConvert.ToDouble (value);
        case TypeCode.Int16: return XmlConvert.ToInt16 (value);
        case TypeCode.Int32: return XmlConvert.ToInt32 (value);
        case TypeCode.Int64: return XmlConvert.ToInt64 (value);
        case TypeCode.SByte: return XmlConvert.ToSByte (value);
        case TypeCode.Single: return XmlConvert.ToSingle (value);
        case TypeCode.UInt16: return XmlConvert.ToUInt16 (value);
        case TypeCode.UInt32: return XmlConvert.ToUInt32 (value);
        case TypeCode.UInt64: return XmlConvert.ToUInt64 (value);
      }

      if (type == typeof (TimeSpan)) return XmlConvert.ToTimeSpan (value);
      if (type == typeof (Guid)) return XmlConvert.ToGuid (value);
      if (type == typeof (byte[])) return Convert.FromBase64String (value);
      if (type == typeof (System.Type)) return System.Type.GetType (value);

      return Convert.ChangeType (value, type);
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.