Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / XmlDataLoader.cs / 1305376 / XmlDataLoader.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
namespace System.Data {
using System;
using System.Collections;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
internal sealed class XmlDataLoader {
DataSet dataSet;
XmlToDatasetMap nodeToSchemaMap = null;
Hashtable nodeToRowMap;
Stack childRowsStack = null;
Hashtable htableExcludedNS = null;
bool fIsXdr = false;
internal bool isDiffgram = false;
DataRow topMostRow = null;
XmlElement topMostNode = null;
bool ignoreSchema = false;
DataTable dataTable;
bool isTableLevel = false;
private bool fromInference = false;
internal XmlDataLoader( DataSet dataset, bool IsXdr, bool ignoreSchema) {
// Initialization
this.dataSet = dataset;
this.nodeToRowMap = new Hashtable();
this.fIsXdr = IsXdr;
this.ignoreSchema = ignoreSchema;
}
internal XmlDataLoader( DataSet dataset, bool IsXdr, XmlElement topNode, bool ignoreSchema) {
// Initialization
this.dataSet = dataset;
this.nodeToRowMap = new Hashtable();
this.fIsXdr = IsXdr;
// Allocate the stack and create the mappings
childRowsStack = new Stack(50);
topMostNode = topNode;
this.ignoreSchema = ignoreSchema;
}
internal XmlDataLoader( DataTable datatable, bool IsXdr, bool ignoreSchema) {
// Initialization
this.dataSet = null;
dataTable = datatable;
isTableLevel = true;
this.nodeToRowMap = new Hashtable();
this.fIsXdr = IsXdr;
this.ignoreSchema = ignoreSchema;
}
internal XmlDataLoader( DataTable datatable, bool IsXdr, XmlElement topNode, bool ignoreSchema) {
// Initialization
this.dataSet = null;
dataTable = datatable;
isTableLevel = true;
this.nodeToRowMap = new Hashtable();
this.fIsXdr = IsXdr;
// Allocate the stack and create the mappings
childRowsStack = new Stack(50);
topMostNode = topNode;
this.ignoreSchema = ignoreSchema;
}
internal bool FromInference {
get {
return fromInference;
}
set {
fromInference = value;
}
}
// after loading, all detached DataRows are attached to their tables
private void AttachRows( DataRow parentRow, XmlNode parentElement ) {
if (parentElement == null)
return;
for (XmlNode n = parentElement.FirstChild; n != null; n = n.NextSibling) {
if (n.NodeType == XmlNodeType.Element) {
XmlElement e = (XmlElement) n;
DataRow r = GetRowFromElement( e );
if (r != null && r.RowState == DataRowState.Detached) {
if (parentRow != null)
r.SetNestedParentRow( parentRow, /*setNonNested*/ false );
r.Table.Rows.Add( r );
}
else if (r == null) {
// n is a 'sugar element'
AttachRows( parentRow, n );
}
// attach all detached rows
AttachRows( r, n );
}
}
}
private int CountNonNSAttributes (XmlNode node) {
int count = 0;
for (int i = 0; i < node.Attributes.Count; i++) {
XmlAttribute attr = node.Attributes[i];
if (!FExcludedNamespace(node.Attributes[i].NamespaceURI))
count++;
}
return count;
}
private string GetValueForTextOnlyColums( XmlNode n ) {
string value = null;
// don't consider whitespace
while (n != null && (n.NodeType == XmlNodeType.Whitespace || !IsTextLikeNode(n.NodeType))) {
n = n.NextSibling;
}
if (n != null) {
if (IsTextLikeNode( n.NodeType ) && (n.NextSibling == null || !IsTextLikeNode( n.NodeType ))) {
// don't use string builder if only one text node exists
value = n.Value;
n = n.NextSibling;
}
else {
StringBuilder sb = new StringBuilder();
while (n != null && IsTextLikeNode( n.NodeType )) {
sb.Append( n.Value );
n = n.NextSibling;
}
value = sb.ToString();
}
}
if (value == null)
value = String.Empty;
return value;
}
private string GetInitialTextFromNodes( ref XmlNode n ) {
string value = null;
if (n != null) {
// don't consider whitespace
while (n.NodeType == XmlNodeType.Whitespace)
n = n.NextSibling;
if (IsTextLikeNode( n.NodeType ) && (n.NextSibling == null || !IsTextLikeNode( n.NodeType ))) {
// don't use string builder if only one text node exists
value = n.Value;
n = n.NextSibling;
}
else {
StringBuilder sb = new StringBuilder();
while (n != null && IsTextLikeNode( n.NodeType )) {
sb.Append( n.Value );
n = n.NextSibling;
}
value = sb.ToString();
}
}
if (value == null)
value = String.Empty;
return value;
}
private DataColumn GetTextOnlyColumn( DataRow row ) {
DataColumnCollection columns = row.Table.Columns;
int cCols = columns.Count;
for (int iCol = 0; iCol < cCols; iCol++) {
DataColumn c = columns[iCol];
if (IsTextOnly( c ))
return c;
}
return null;
}
internal DataRow GetRowFromElement( XmlElement e ) {
return(DataRow) nodeToRowMap[e];
}
internal bool FColumnElement(XmlElement e) {
if (nodeToSchemaMap.GetColumnSchema(e, FIgnoreNamespace(e)) == null)
return false;
if (CountNonNSAttributes(e) > 0)
return false;
for (XmlNode tabNode = e.FirstChild; tabNode != null; tabNode = tabNode.NextSibling)
if (tabNode is XmlElement)
return false;
return true;
}
private bool FExcludedNamespace(string ns) {
if (ns.Equals(Keywords.XSD_XMLNS_NS))
return true;
if (htableExcludedNS == null)
return false;
return htableExcludedNS.Contains(ns);
}
private bool FIgnoreNamespace(XmlNode node) {
XmlNode ownerNode;
if (!fIsXdr)
return false;
if (node is XmlAttribute)
ownerNode = ((XmlAttribute)node).OwnerElement;
else
ownerNode = node;
if (ownerNode.NamespaceURI.StartsWith("x-schema:#", StringComparison.Ordinal))
return true;
else
return false;
}
private bool FIgnoreNamespace(XmlReader node) {
if (fIsXdr && node.NamespaceURI.StartsWith("x-schema:#", StringComparison.Ordinal))
return true;
else
return false;
}
internal bool IsTextLikeNode( XmlNodeType n ) {
switch (n) {
case XmlNodeType.EntityReference:
throw ExceptionBuilder.FoundEntity();
case XmlNodeType.Text:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
case XmlNodeType.CDATA:
return true;
default:
return false;
}
}
internal bool IsTextOnly( DataColumn c ) {
if (c.ColumnMapping != MappingType.SimpleContent)
return false;
else
return true;
}
internal void LoadData( XmlDocument xdoc ) {
if (xdoc.DocumentElement == null)
return;
bool saveEnforce;
if (isTableLevel) {
saveEnforce = dataTable.EnforceConstraints;
dataTable.EnforceConstraints = false;
}
else {
saveEnforce = dataSet.EnforceConstraints;
dataSet.EnforceConstraints = false;
dataSet.fInReadXml = true;
}
if (isTableLevel) {
nodeToSchemaMap = new XmlToDatasetMap(dataTable, xdoc.NameTable);
}
else {
nodeToSchemaMap = new XmlToDatasetMap(dataSet, xdoc.NameTable);
}
/*
// Top level table or dataset ?
XmlElement rootElement = xdoc.DocumentElement;
Hashtable tableAtoms = new Hashtable();
XmlNode tabNode;
if (CountNonNSAttributes (rootElement) > 0)
dataSet.fTopLevelTable = true;
else {
for (tabNode = rootElement.FirstChild; tabNode != null; tabNode = tabNode.NextSibling) {
if (tabNode is XmlElement && tabNode.LocalName != Keywords.XSD_SCHEMA) {
object value = tableAtoms[QualifiedName (tabNode.LocalName, tabNode.NamespaceURI)];
if (value == null || (bool)value == false) {
dataSet.fTopLevelTable = true;
break;
}
}
}
}
*/
DataRow topRow = null;
if (isTableLevel ||(dataSet!= null && dataSet.fTopLevelTable) ){
XmlElement e = xdoc.DocumentElement;
DataTable topTable = (DataTable) nodeToSchemaMap.GetSchemaForNode(e, FIgnoreNamespace(e));
if (topTable != null) {
topRow = topTable.CreateEmptyRow(); //[....] perf
nodeToRowMap[ e ] = topRow;
// get all field values.
LoadRowData( topRow, e );
topTable.Rows.Add(topRow);
}
}
LoadRows( topRow, xdoc.DocumentElement );
AttachRows( topRow, xdoc.DocumentElement );
if (isTableLevel) {
dataTable.EnforceConstraints = saveEnforce;
}
else {
dataSet.fInReadXml = false;
dataSet.EnforceConstraints = saveEnforce;
}
}
private void LoadRowData(DataRow row, XmlElement rowElement) {
XmlNode n;
DataTable table = row.Table;
if (FromInference)
table.Prefix = rowElement.Prefix;
// keep a list of all columns that get updated
Hashtable foundColumns = new Hashtable();
row.BeginEdit();
// examine all children first
n = rowElement.FirstChild;
// Look for data to fill the TextOnly column
DataColumn column = GetTextOnlyColumn( row );
if (column != null) {
foundColumns[column] = column;
string text = GetValueForTextOnlyColums( n ) ;
if (XMLSchema.GetBooleanAttribute(rowElement, Keywords.XSI_NIL, Keywords.XSINS, false) && Common.ADP.IsEmpty(text) )
row[column] = DBNull.Value;
else
SetRowValueFromXmlText( row, column, text );
}
// Walk the region to find elements that map to columns
while (n != null && n != rowElement) {
if (n.NodeType == XmlNodeType.Element) {
XmlElement e = (XmlElement) n;
object schema = nodeToSchemaMap.GetSchemaForNode( e, FIgnoreNamespace(e) );
if (schema is DataTable) {
if (FColumnElement(e))
schema = nodeToSchemaMap.GetColumnSchema( e, FIgnoreNamespace(e) );
}
// if element has its own table mapping, it is a separate region
if (schema == null || schema is DataColumn) {
// descend to examine child elements
n = e.FirstChild;
if (schema != null && schema is DataColumn) {
DataColumn c = (DataColumn) schema;
if (c.Table == row.Table && c.ColumnMapping != MappingType.Attribute && foundColumns[c] == null) {
foundColumns[c] = c;
string text = GetValueForTextOnlyColums( n ) ;
if (XMLSchema.GetBooleanAttribute(e, Keywords.XSI_NIL, Keywords.XSINS, false) && Common.ADP.IsEmpty(text) )
row[c] = DBNull.Value;
else
SetRowValueFromXmlText( row, c, text );
}
}
else if ((schema == null) && (n!=null)) {
continue;
}
// nothing left down here, continue from element
if (n == null)
n = e;
}
}
// if no more siblings, ascend back toward original element (rowElement)
while (n != rowElement && n.NextSibling == null) {
n = n.ParentNode;
}
if (n != rowElement)
n = n.NextSibling;
}
//
// Walk the attributes to find attributes that map to columns.
//
foreach( XmlAttribute attr in rowElement.Attributes ) {
object schema = nodeToSchemaMap.GetColumnSchema( attr, FIgnoreNamespace(attr) );
if (schema != null && schema is DataColumn) {
DataColumn c = (DataColumn) schema;
if (c.ColumnMapping == MappingType.Attribute && foundColumns[c] == null) {
foundColumns[c] = c;
n = attr.FirstChild;
SetRowValueFromXmlText( row, c, GetInitialTextFromNodes( ref n ) );
}
}
}
// Null all columns values that aren't represented in the tree
foreach( DataColumn c in row.Table.Columns ) {
if (foundColumns[c] == null && XmlToDatasetMap.IsMappedColumn(c)) {
if (!c.AutoIncrement) {
if (c.AllowDBNull) {
row[c] = DBNull.Value;
}
else {
row[c] = c.DefaultValue;
}
}
else {
c.Init(row.tempRecord);
}
}
}
row.EndEdit();
}
// load all data from tree structre into datarows
private void LoadRows( DataRow parentRow, XmlNode parentElement ) {
if (parentElement == null)
return;
// Skip schema node as well
if (parentElement.LocalName == Keywords.XSD_SCHEMA && parentElement.NamespaceURI == Keywords.XSDNS ||
parentElement.LocalName == Keywords.SQL_[....] && parentElement.NamespaceURI == Keywords.UPDGNS ||
parentElement.LocalName == Keywords.XDR_SCHEMA && parentElement.NamespaceURI == Keywords.XDRNS)
return;
for (XmlNode n = parentElement.FirstChild; n != null; n = n.NextSibling) {
if (n is XmlElement) {
XmlElement e = (XmlElement) n;
object schema = nodeToSchemaMap.GetSchemaForNode( e, FIgnoreNamespace(e) );
if (schema != null && schema is DataTable) {
DataRow r = GetRowFromElement( e );
if (r == null) {
// skip columns which has the same name as another table
if (parentRow != null && FColumnElement(e))
continue;
r = ((DataTable)schema).CreateEmptyRow();
nodeToRowMap[ e ] = r;
// get all field values.
LoadRowData( r, e );
}
// recurse down to inner elements
LoadRows( r, n );
}
else {
// recurse down to inner elements
LoadRows( null, n );
}
}
}
}
private void SetRowValueFromXmlText( DataRow row, DataColumn col, string xmlText ) {
row[col] = col.ConvertXmlToObject(xmlText);
}
internal void LoadTopMostRow(ref bool[] foundColumns) {
// Attempt to load row from top node we backed up in DataSet.ReadXml()
// In most cases it contains the DataSet name and no information
// Check if DataSet object matches the top node (it won't in most cases)
Object obj = nodeToSchemaMap.GetSchemaForNode(topMostNode,FIgnoreNamespace(topMostNode));
if (obj is DataTable) { // It's a table? Load it.
DataTable table = (DataTable) obj;
topMostRow = table.CreateEmptyRow();
foundColumns = new bool[topMostRow.Table.Columns.Count];
//
// Walk the attributes to find attributes that map to columns.
//
foreach( XmlAttribute attr in topMostNode.Attributes ) {
object schema = nodeToSchemaMap.GetColumnSchema( attr, FIgnoreNamespace(attr) );
if (schema != null && schema is DataColumn) {
DataColumn c = (DataColumn) schema;
if (c.ColumnMapping == MappingType.Attribute) {
XmlNode n = attr.FirstChild;
SetRowValueFromXmlText( topMostRow, c, GetInitialTextFromNodes( ref n ) );
foundColumns[c.Ordinal] = true;
}
}
}
}
topMostNode = null;
}
private XmlReader dataReader = null;
private object XSD_XMLNS_NS;
private object XDR_SCHEMA;
private object XDRNS;
private object SQL_[....];
private object UPDGNS;
private object XSD_SCHEMA;
private object XSDNS;
private object DFFNS;
private object MSDNS;
private object DIFFID;
private object HASCHANGES;
private object ROWORDER;
private void InitNameTable() {
XmlNameTable nameTable = dataReader.NameTable;
XSD_XMLNS_NS = nameTable.Add(Keywords.XSD_XMLNS_NS);
XDR_SCHEMA = nameTable.Add(Keywords.XDR_SCHEMA);
XDRNS = nameTable.Add(Keywords.XDRNS);
SQL_[....] = nameTable.Add(Keywords.SQL_[....]);
UPDGNS = nameTable.Add(Keywords.UPDGNS);
XSD_SCHEMA = nameTable.Add(Keywords.XSD_SCHEMA);
XSDNS = nameTable.Add(Keywords.XSDNS);
DFFNS = nameTable.Add(Keywords.DFFNS);
MSDNS = nameTable.Add(Keywords.MSDNS);
DIFFID = nameTable.Add(Keywords.DIFFID);
HASCHANGES = nameTable.Add(Keywords.HASCHANGES);
ROWORDER = nameTable.Add(Keywords.ROWORDER);
}
internal void LoadData(XmlReader reader) {
dataReader = DataTextReader.CreateReader(reader);
int entryDepth = dataReader.Depth; // Store current XML element depth so we'll read
// correct portion of the XML and no more
bool fEnforce = isTableLevel ? dataTable.EnforceConstraints : dataSet.EnforceConstraints;
// Keep constraints status for datataset/table
InitNameTable(); // Adds DataSet namespaces to reader's nametable
if (nodeToSchemaMap == null) { // Create XML to dataset map
nodeToSchemaMap = isTableLevel ? new XmlToDatasetMap(dataReader.NameTable, dataTable) :
new XmlToDatasetMap(dataReader.NameTable, dataSet);
}
if (isTableLevel) {
dataTable.EnforceConstraints = false; // Disable constraints
}
else {
dataSet.EnforceConstraints = false; // Disable constraints
dataSet.fInReadXml = true; // We're in ReadXml now
}
if (topMostNode != null) { // Do we have top node?
if (!isDiffgram && !isTableLevel) { // Not a diffgram and not DataSet?
DataTable table = nodeToSchemaMap.GetSchemaForNode(topMostNode, FIgnoreNamespace(topMostNode)) as DataTable;
// Try to match table in the dataset to this node
if (table != null) { // Got the table ?
LoadTopMostTable(table); // Load top most node
}
}
topMostNode = null; // topMostNode is no more. Good riddance.
}
while( !dataReader.EOF ) { // Main XML parsing loop. Check for EOF just in case.
if (dataReader.Depth < entryDepth) // Stop if we have consumed all elements allowed
break;
if ( reader.NodeType != XmlNodeType.Element ) { // Read till Element is found
dataReader.Read();
continue;
}
DataTable table = nodeToSchemaMap.GetTableForNode(dataReader, FIgnoreNamespace(dataReader));
// Try to get table for node
if (table == null) { // Read till table is found
if (!ProcessXsdSchema()) // Check for schemas...
dataReader.Read(); // Not found? Read next element.
continue;
}
LoadTable(table, false /* isNested */); // Here goes -- load data for this table
// This is a root table, so it's not nested
}
if (isTableLevel) {
dataTable.EnforceConstraints = fEnforce; // Restore constraints and return
}
else {
dataSet.fInReadXml = false; // We're done.
dataSet.EnforceConstraints = fEnforce; // Restore constraints and return
}
}
// Loads a top most table.
// This is neded because desktop is capable of loading almost anything into the dataset.
// The top node could be a DataSet element or a Table element. To make things worse,
// you could have a table with the same name as dataset.
// Here's how we're going to dig into this mess:
//
// TopNode is null ?
// / No \ Yes
// Table matches TopNode ? Current node is the table start
// / No \ Yes (LoadTopMostTable called in this case only)
// Current node is the table start DataSet name matches one of the tables ?
// TopNode is dataset node / Yes \ No
// / TopNode is the table
// Current node matches column or nested table in the table ? and current node
// / No \ Yes is a column or a
// TopNode is DataSet TopNode is table nested table
//
// Yes, it is terrible and I don't like it also..
private void LoadTopMostTable(DataTable table) {
// /------------------------------- This one is in topMostNode (backed up to XML DOM)
// Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ByteStorage.cs
- Compilation.cs
- NativeMethods.cs
- ConfigXmlSignificantWhitespace.cs
- SizeChangedInfo.cs
- PersonalizationAdministration.cs
- VirtualDirectoryMapping.cs
- ClientTargetSection.cs
- EmptyCollection.cs
- Vector3DCollectionValueSerializer.cs
- PageAsyncTaskManager.cs
- WebExceptionStatus.cs
- FrameworkElement.cs
- MenuEventArgs.cs
- DataFormat.cs
- SqlDataSourceQueryEditor.cs
- RequestContext.cs
- QilPatternFactory.cs
- SortQuery.cs
- ConfigXmlAttribute.cs
- SimpleTextLine.cs
- XmlIncludeAttribute.cs
- ViewKeyConstraint.cs
- ThicknessAnimation.cs
- RegexCharClass.cs
- PropertyTabChangedEvent.cs
- WebWorkflowRole.cs
- ConsoleCancelEventArgs.cs
- RC2.cs
- Msmq3PoisonHandler.cs
- ProcessHostFactoryHelper.cs
- NullableDoubleMinMaxAggregationOperator.cs
- PrintDialog.cs
- ChangePassword.cs
- MobileRedirect.cs
- SqlDataAdapter.cs
- ToolboxBitmapAttribute.cs
- ActivityWithResultWrapper.cs
- GenericIdentity.cs
- ObjectReferenceStack.cs
- PageHandlerFactory.cs
- PageVisual.cs
- SystemIPInterfaceProperties.cs
- ProviderUtil.cs
- WebPartAuthorizationEventArgs.cs
- Attribute.cs
- UniqueIdentifierService.cs
- ConfigurationException.cs
- Function.cs
- ipaddressinformationcollection.cs
- StringCollection.cs
- httpstaticobjectscollection.cs
- AsymmetricKeyExchangeDeformatter.cs
- LocalFileSettingsProvider.cs
- SystemIcmpV6Statistics.cs
- OdbcCommand.cs
- ScalarOps.cs
- Formatter.cs
- Item.cs
- ConnectionManager.cs
- CodeRemoveEventStatement.cs
- TableLayoutPanel.cs
- RequestBringIntoViewEventArgs.cs
- IdentitySection.cs
- EventlogProvider.cs
- CleanUpVirtualizedItemEventArgs.cs
- ServiceProviders.cs
- Types.cs
- Run.cs
- BinaryParser.cs
- BindingCollectionElement.cs
- XmlQualifiedName.cs
- TreeNodeStyleCollection.cs
- EdmConstants.cs
- SymDocumentType.cs
- TextElementEditingBehaviorAttribute.cs
- MediaSystem.cs
- InkSerializer.cs
- Choices.cs
- LineGeometry.cs
- SmtpFailedRecipientException.cs
- Style.cs
- FilterElement.cs
- AutoGeneratedField.cs
- RNGCryptoServiceProvider.cs
- QilLoop.cs
- EntryPointNotFoundException.cs
- ProcessModelInfo.cs
- DateTimeStorage.cs
- WSHttpBindingElement.cs
- HtmlEncodedRawTextWriter.cs
- Debug.cs
- ExeContext.cs
- Vector.cs
- PersonalizablePropertyEntry.cs
- DBConcurrencyException.cs
- SynchronizationScope.cs
- ObjectStateEntryDbDataRecord.cs
- UrlMappingCollection.cs
- LicenseProviderAttribute.cs