internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving) { IntPtr hscp; Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, mode=%d{ds.XmlReadMode}, denyResolving=%d{bool}\n", ObjectID, (int)mode, denyResolving); try { XmlReadMode ret = mode; if (reader == null) return ret; if (mode == XmlReadMode.Auto) { // Dev11 915079: nested ReadXml calls on the same DataSet must be done outside of RowDiffIdUsage scope return ReadXml(reader); } DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection(); try { bool fSchemaFound = false; bool fDataFound = false; bool fIsXdr = false; int iCurrentDepth = -1; // Dev11 904428: prepare and cleanup rowDiffId hashtable rowDiffIdUsage.Prepare(this); 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(); 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)) { this.ReadXmlDiffgram(reader); // read the closing tag of the current element ReadEndElement(reader); } else { reader.Skip(); } return ret; } if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) { // load XDR schema and exit if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) && (mode != XmlReadMode.InferTypedSchema)) { ReadXDRSchema(reader); } else { reader.Skip(); } 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) && (mode != XmlReadMode.InferTypedSchema)) { ReadXSDSchema(reader, denyResolving); } else reader.Skip(); 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)) 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) && (mode != XmlReadMode.InferTypedSchema)) { 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) && (mode != XmlReadMode.InferTypedSchema)) { ReadXSDSchema(reader, denyResolving); fSchemaFound = true; } else { reader.Skip(); } continue; } if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) { if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) { 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)) 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 || mode == XmlReadMode.InferTypedSchema) { //save the node in DOM until the end; XmlNode node = xdoc.ReadNode(reader); topNode.AppendChild(node); } else { 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 return ret; } // Load Data if (mode == XmlReadMode.InferSchema || mode == XmlReadMode.InferTypedSchema) { InferSchema(xdoc, null, mode); ret = XmlReadMode.InferSchema; xmlload.FromInference = true; // } try { xmlload.LoadData(xdoc); } finally { xmlload.FromInference = false; } } } return ret; } finally { // Dev11 904428: prepare and cleanup rowDiffId hashtable rowDiffIdUsage.Cleanup(); } } finally { Bid.ScopeLeave(ref hscp); } }
internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving) { IntPtr hscp; Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, denyResolving=%d{bool}\n", 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)) { this.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)) { this.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)) { this.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 = this.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 this.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 = this.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 (this.DataSetName != root.Name && this.namespaceURI != root.NamespaceURI && Tables.Contains(root.Name, (root.NamespaceURI.Length == 0) ? null : root.NamespaceURI, false, true)) { this.fTopLevelTable = true; } try { xmlload.LoadData(xdoc); } finally { this.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) this.fTopLevelTable = tmpValue; } } return ret; } finally { rowDiffIdUsage.Cleanup(); } } finally { Bid.ScopeLeave(ref hscp); } }