internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
{
DataTable.RowDiffIdUsageSection rowDiffIdUsage = new DataTable.RowDiffIdUsageSection();
try {
bool fSchemaFound = false;
bool fDataFound = false;
bool fIsXdr = false;
int iCurrentDepth = -1;
XmlReadMode ret = mode;
// Dev11 904428: prepare and cleanup rowDiffId hashtable
rowDiffIdUsage.Prepare(this);
if (reader == null)
return ret;
bool originalEnforceConstraint = false;
if (this.DataSet != null) {
originalEnforceConstraint = this.DataSet.EnforceConstraints;
this.DataSet.EnforceConstraints = false;
}
else {
originalEnforceConstraint = this.EnforceConstraints;
this.EnforceConstraints = false;
}
if (reader is XmlTextReader)
((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.Significant;
XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
if ((mode != XmlReadMode.Fragment) && (reader.NodeType == XmlNodeType.Element))
iCurrentDepth = reader.Depth;
reader.MoveToContent();
if (Columns.Count == 0) {
if (IsEmptyXml(reader)) {
reader.Read();
return ret;
}
}
XmlDataLoader xmlload = null;
if (reader.NodeType == XmlNodeType.Element) {
XmlElement topNode = null;
if (mode == XmlReadMode.Fragment) {
xdoc.AppendChild(xdoc.CreateElement("ds_sqlXmlWraPPeR"));
topNode = xdoc.DocumentElement;
}
else { //handle the top node
if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
if (Columns.Count == 0) {
if(reader.IsEmptyElement) {
reader.Read();
return XmlReadMode.DiffGram;
}
throw ExceptionBuilder.DataTableInferenceNotSupported();
}
this.ReadXmlDiffgram(reader);
// read the closing tag of the current element
ReadEndElement(reader);
}
else {
reader.Skip();
}
RestoreConstraint(originalEnforceConstraint);
return ret;
}
if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
// load XDR schema and exit
if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
ReadXDRSchema(reader);
}
else {
reader.Skip();
}
RestoreConstraint(originalEnforceConstraint);
return ret; //since the top level element is a schema return
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
// load XSD schema and exit
if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
ReadXmlSchema(reader, denyResolving);
}
else
reader.Skip();
RestoreConstraint(originalEnforceConstraint);
return ret; //since the top level element is a schema return
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
}
else {
this.enforceConstraints = originalEnforceConstraint;
}
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
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();
}
while(MoveToElement(reader, iCurrentDepth)) {
if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
// load XDR schema
if (!fSchemaFound && !fDataFound && (mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
ReadXDRSchema(reader);
fSchemaFound = true;
fIsXdr = true;
}
else {
reader.Skip();
}
continue;
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
// load XSD schema and exit
if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
ReadXmlSchema(reader, denyResolving);
fSchemaFound = true;
}
else {
reader.Skip();
}
continue;
}
if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
if (Columns.Count == 0) {
if(reader.IsEmptyElement) {
reader.Read();
return XmlReadMode.DiffGram;
}
throw ExceptionBuilder.DataTableInferenceNotSupported();
}
this.ReadXmlDiffgram(reader);
ret = XmlReadMode.DiffGram;
}
else {
reader.Skip();
}
continue;
}
if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
}
else {
this.enforceConstraints = originalEnforceConstraint;
}
throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
}
if (mode == XmlReadMode.DiffGram) {
reader.Skip();
continue; // we do not read data in diffgram mode
}
// if we are here we found some data
fDataFound = true;
if (mode == XmlReadMode.InferSchema) { //save the node in DOM until the end;
XmlNode node = xdoc.ReadNode(reader);
topNode.AppendChild(node);
}
else {
if (Columns.Count == 0) {
throw ExceptionBuilder.DataTableInferenceNotSupported();
}
if (xmlload == null)
xmlload = new XmlDataLoader(this, fIsXdr, topNode, mode == XmlReadMode.IgnoreSchema);
xmlload.LoadData(reader);
}
} //end of the while
// read the closing tag of the current element
ReadEndElement(reader);
// now top node contains the data part
xdoc.AppendChild(topNode);
if (xmlload == null)
xmlload = new XmlDataLoader(this, fIsXdr, mode == XmlReadMode.IgnoreSchema);
if (mode == XmlReadMode.DiffGram) {
// we already got the diffs through XmlReader interface
RestoreConstraint(originalEnforceConstraint);
return ret;
}
//todo
// Load Data
if (mode == XmlReadMode.InferSchema) {
if (Columns.Count == 0) {
throw ExceptionBuilder.DataTableInferenceNotSupported();
}
// [....] xmlload.InferSchema(xdoc, null);
// [....] xmlload.LoadData(xdoc);
}
}
RestoreConstraint(originalEnforceConstraint);
return ret;
}
finally {
// Dev11 904428: prepare and cleanup rowDiffId hashtable
rowDiffIdUsage.Cleanup();
}
}