// LAMESPEC: XmlReadMode.Fragment is far from presisely
// documented. MS.NET infers schema against this mode.
public XmlReadMode ReadXml (XmlReader input, XmlReadMode mode)
{
switch (input.ReadState) {
case ReadState.EndOfFile:
case ReadState.Error:
case ReadState.Closed:
return mode;
}
// Skip XML declaration and prolog
input.MoveToContent ();
if (input.EOF)
return mode;
// FIXME: We need more decent code here, but for now
// I don't know the precise MS.NET behavior, I just
// delegate to specific read process.
switch (mode) {
case XmlReadMode.IgnoreSchema:
return ReadXmlIgnoreSchema (input, mode, true);
case XmlReadMode.ReadSchema:
return ReadXmlReadSchema (input, mode, true);
}
// remaining modes are: Auto, InferSchema, Fragment, Diffgram
XmlReader reader = input;
int depth = reader.Depth;
XmlReadMode result = mode;
bool skippedTopLevelElement = false;
string potentialDataSetName = null;
XmlDocument doc = null;
bool shouldReadData = mode != XmlReadMode.DiffGram;
bool shouldNotInfer = Tables.Count > 0;
switch (mode) {
case XmlReadMode.Auto:
case XmlReadMode.InferSchema:
doc = new XmlDocument ();
do {
doc.AppendChild (doc.ReadNode (reader));
} while (!reader.EOF &&
doc.DocumentElement == null);
reader = new XmlNodeReader (doc);
reader.MoveToContent ();
break;
case XmlReadMode.DiffGram:
if (!(reader.LocalName == "diffgram" &&
reader.NamespaceURI == XmlConstants.DiffgrNamespace))
goto case XmlReadMode.Auto;
break;
}
switch (mode) {
case XmlReadMode.Auto:
case XmlReadMode.InferSchema:
case XmlReadMode.ReadSchema:
if (!(reader.LocalName == "diffgram" &&
reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
!(reader.LocalName == "schema" &&
reader.NamespaceURI == XmlSchema.Namespace))
potentialDataSetName = reader.LocalName;
goto default;
case XmlReadMode.Fragment:
break;
default:
if (!(reader.LocalName == "diffgram" &&
reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
!(reader.LocalName == "schema" &&
reader.NamespaceURI == XmlSchema.Namespace)) {
if (!reader.IsEmptyElement) {
reader.Read ();
reader.MoveToContent ();
skippedTopLevelElement = true;
}
else {
switch (mode) {
case XmlReadMode.Auto:
case XmlReadMode.InferSchema:
DataSetName = reader.LocalName;
break;
}
reader.Read ();
}
}
break;
}
// If schema, then read the first element as schema
if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
shouldNotInfer = true;
switch (mode) {
case XmlReadMode.IgnoreSchema:
case XmlReadMode.InferSchema:
reader.Skip ();
break;
case XmlReadMode.Fragment:
ReadXmlSchema (reader);
break;
case XmlReadMode.DiffGram:
case XmlReadMode.Auto:
if (Tables.Count == 0) {
ReadXmlSchema (reader);
if (mode == XmlReadMode.Auto)
result = XmlReadMode.ReadSchema;
} else {
// otherwise just ignore and return IgnoreSchema
reader.Skip ();
result = XmlReadMode.IgnoreSchema;
}
break;
case XmlReadMode.ReadSchema:
ReadXmlSchema (reader);
break;
}
}
// If diffgram, then read the first element as diffgram
if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
switch (mode) {
case XmlReadMode.Auto:
case XmlReadMode.IgnoreSchema:
case XmlReadMode.DiffGram:
XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
DiffLoader.Load (reader);
if (mode == XmlReadMode.Auto)
result = XmlReadMode.DiffGram;
shouldReadData = false;
break;
case XmlReadMode.Fragment:
reader.Skip ();
break;
default:
reader.Skip ();
break;
}
}
// if schema after diffgram, just skip it.
if (!shouldReadData && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
shouldNotInfer = true;
switch (mode) {
default:
reader.Skip ();
break;
case XmlReadMode.ReadSchema:
case XmlReadMode.DiffGram:
if (Tables.Count == 0)
ReadXmlSchema (reader);
break;
}
}
if (reader.EOF)
return result == XmlReadMode.Auto ?
potentialDataSetName != null && !shouldNotInfer ?
XmlReadMode.InferSchema :
XmlReadMode.IgnoreSchema : result;
// Otherwise, read as dataset... but only when required.
if (shouldReadData && !shouldNotInfer) {
switch (mode) {
case XmlReadMode.Auto:
if (Tables.Count > 0)
goto case XmlReadMode.IgnoreSchema;
else
goto case XmlReadMode.InferSchema;
case XmlReadMode.InferSchema:
InferXmlSchema (doc, null);
if (mode == XmlReadMode.Auto)
result = XmlReadMode.InferSchema;
break;
case XmlReadMode.IgnoreSchema:
case XmlReadMode.Fragment:
case XmlReadMode.DiffGram:
break;
default:
shouldReadData = false;
break;
}
}
if (shouldReadData) {
XmlReader dataReader = reader;
if (doc != null) {
dataReader = new XmlNodeReader (doc);
dataReader.MoveToContent ();
}
if (reader.NodeType == XmlNodeType.Element)
XmlDataReader.ReadXml (this, dataReader,
mode);
}
if (skippedTopLevelElement) {
switch (result) {
case XmlReadMode.Auto:
case XmlReadMode.InferSchema:
// DataSetName = potentialDataSetName;
// result = XmlReadMode.InferSchema;
break;
}
if (reader.NodeType == XmlNodeType.EndElement)
reader.ReadEndElement ();
}
//*
while (input.Depth > depth)
input.Read ();
if (input.NodeType == XmlNodeType.EndElement)
input.Read ();
//*/
input.MoveToContent ();
return result == XmlReadMode.Auto ?
XmlReadMode.IgnoreSchema : result;
}