internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
{
long logScopeId = DataCommonEventSource.Log.EnterScope("<ds.DataSet.ReadXml|INFO> {0}, denyResolving={1}", ObjectID, denyResolving);
try
{
DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
try
{
bool fDataFound = false;
bool fSchemaFound = false;
bool fDiffsFound = false;
bool fIsXdr = false;
int iCurrentDepth = -1;
XmlReadMode ret = XmlReadMode.Auto;
bool isEmptyDataSet = false;
bool topNodeIsProcessed = false; // we chanche topnode and there is just one case that we miss to process it
// it is : <elem attrib1="Attrib">txt</elem>
// clear the hashtable to avoid conflicts between diffgrams, SqlHotFix 782
rowDiffIdUsage.Prepare(this);
if (reader == null)
{
return ret;
}
if (Tables.Count == 0)
{
isEmptyDataSet = true;
}
if (reader is XmlTextReader)
{
((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.Significant;
}
XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
XmlDataLoader xmlload = null;
reader.MoveToContent();
if (reader.NodeType == XmlNodeType.Element)
{
iCurrentDepth = reader.Depth;
}
if (reader.NodeType == XmlNodeType.Element)
{
if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS))
{
ReadXmlDiffgram(reader);
// read the closing tag of the current element
ReadEndElement(reader);
return XmlReadMode.DiffGram;
}
// if reader points to the schema load it
if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS)
{
// load XDR schema and exit
ReadXDRSchema(reader);
return XmlReadMode.ReadSchema; //since the top level element is a schema return
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS)
{
// load XSD schema and exit
ReadXSDSchema(reader, denyResolving);
return XmlReadMode.ReadSchema; //since the top level element is a schema return
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
{
throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
}
// now either the top level node is a table and we load it through dataReader...
// ... or backup the top node and all its attributes because we may need to InferSchema
XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
if (reader.HasAttributes)
{
int attrCount = reader.AttributeCount;
for (int i = 0; i < attrCount; i++)
{
reader.MoveToAttribute(i);
if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
else
{
XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
attr.Prefix = reader.Prefix;
attr.Value = reader.GetAttribute(i);
}
}
}
reader.Read();
string rootNodeSimpleContent = reader.Value;
while (MoveToElement(reader, iCurrentDepth))
{
if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS))
{
ReadXmlDiffgram(reader);
// read the closing tag of the current element
// YUKON FIX ReadEndElement(reader);
// return XmlReadMode.DiffGram;
ret = XmlReadMode.DiffGram; // continue reading for multiple schemas
}
// if reader points to the schema load it...
if (!fSchemaFound && !fDataFound && reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS)
{
// load XDR schema and exit
ReadXDRSchema(reader);
fSchemaFound = true;
fIsXdr = true;
continue;
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS)
{
// load XSD schema and exit
ReadXSDSchema(reader, denyResolving);
fSchemaFound = true;
continue;
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
{
throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
}
if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS))
{
ReadXmlDiffgram(reader);
fDiffsFound = true;
ret = XmlReadMode.DiffGram;
}
else
{
// We have found data IFF the reader.NodeType == Element and reader.depth == currentDepth-1
// if reader.NodeType == whitespace, skip all white spaces.
// skip processing i.e. continue if the first non-whitespace node is not of type element.
while (!reader.EOF && reader.NodeType == XmlNodeType.Whitespace)
reader.Read();
if (reader.NodeType != XmlNodeType.Element)
continue;
// we found data here
fDataFound = true;
if (!fSchemaFound && Tables.Count == 0)
{
XmlNode node = xdoc.ReadNode(reader);
topNode.AppendChild(node);
}
else
{
if (xmlload == null)
{
xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
}
xmlload.LoadData(reader);
topNodeIsProcessed = true; // we process the topnode
if (fSchemaFound)
{
ret = XmlReadMode.ReadSchema;
}
else
{
ret = XmlReadMode.IgnoreSchema;
}
}
}
}
// read the closing tag of the current element
ReadEndElement(reader);
bool isfTopLevelTableSet = false;
bool tmpValue = _fTopLevelTable;
//While inference we ignore root elements text content
if (!fSchemaFound && Tables.Count == 0 && !topNode.HasChildNodes)
{
//We shoule not come add SC of root elemnt to topNode if we are not infering
_fTopLevelTable = true;
isfTopLevelTableSet = true;
if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
{
topNode.InnerText = rootNodeSimpleContent;
}
}
if (!isEmptyDataSet)
{
if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
{
topNode.InnerText = rootNodeSimpleContent;
}
}
// now top node contains the data part
xdoc.AppendChild(topNode);
if (xmlload == null)
{
xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
}
if (!isEmptyDataSet && !topNodeIsProcessed)
{
XmlElement root = xdoc.DocumentElement;
Debug.Assert(root.NamespaceURI != null, "root.NamespaceURI should not ne null, it should be empty string");
// just recognize that below given Xml represents datatable in toplevel
//<table attr1="foo" attr2="bar" table_Text="junk">text</table>
// only allow root element with simple content, if any
if (root.ChildNodes.Count == 0 || ((root.ChildNodes.Count == 1) && root.FirstChild.GetType() == typeof(System.Xml.XmlText)))
{
bool initfTopLevelTable = _fTopLevelTable;
// if root element maps to a datatable
// ds and dt cant have the samm name and ns at the same time, how to write to xml
if (DataSetName != root.Name && _namespaceURI != root.NamespaceURI &&
Tables.Contains(root.Name, (root.NamespaceURI.Length == 0) ? null : root.NamespaceURI, false, true))
{
_fTopLevelTable = true;
}
try
{
xmlload.LoadData(xdoc);
}
finally
{
_fTopLevelTable = initfTopLevelTable; // this is not for inference, we have schema and we were skipping
// topnode where it was a datatable, We must restore the value
}
}
}
// above check and below check are orthogonal
// so we InferSchema
if (!fDiffsFound)
{
// Load Data
if (!fSchemaFound && Tables.Count == 0)
{
InferSchema(xdoc, null, XmlReadMode.Auto);
ret = XmlReadMode.InferSchema;
xmlload.FromInference = true;
try
{
xmlload.LoadData(xdoc);
}
finally
{
xmlload.FromInference = false;
}
}
//We dont need this assignement. Once we set it(where we set it during inference), it won't be changed
if (isfTopLevelTableSet)
_fTopLevelTable = tmpValue;
}
}
return ret;
}
finally
{
rowDiffIdUsage.Cleanup();
}
}
finally
{
DataCommonEventSource.Log.ExitScope(logScopeId);
}
}