xsd:restriction does it work with dataset.readxml ?

M

Mac

I'm trying to validate input from an xml source to a dataset in
dotnet2.0. As far as I can see, type errors correctly cause an
exception, but values that are the correct type but do not satisify
xsd:restriction conditions are ingested without a murmur. Is this a bug
or a feature?
Very frustrating.

Evidence:
1) XML data
<?xml version="1.0" encoding="utf-8"?>
<dataset xmlns="http://tempuri.org/DataSet1.xsd">
<datarow>
<c1>row1</c1>
<c2>5</c2>
</datarow>
<datarow>
<c1>row2</c1>
<c2>10</c2>
</datarow>
</dataset>

2) code fragment to read into a dataset (body of a button click
handler.
protected void Button1_Click(object sender, EventArgs e)
{
XmlReader rdr = new XmlTextReader(Server.MapPath(".\\" +
"XMLfile.xml"));
DataSet dsforload = new DataSet();
dsforload.ReadXmlSchema(Server.MapPath(".\\" +
"App_Code\\DataSet1.xsd"));
dsforload.ReadXml(rdr, XmlReadMode.Auto);
GridView1.DataSource = dsforload;
GridView1.DataBind();
}

3) complete xsd schema; quite a lot of random crap generated by the
'DataSet' wizard of VWD2005 - the interesting bit is at the bottom
xmlns="http://tempuri.org/DataSet1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
xmlns:msprop="urn:schemas-microsoft-com:xml-msprop"
attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:annotation>
<xs:appinfo source="urn:schemas-microsoft-com:xml-msdatasource">
<DataSource DefaultConnectionIndex="0"
FunctionsComponentName="QueriesTableAdapter"
Modifier="AutoLayout, AnsiClass, Class, Public"

xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<Connections>
</Connections>
<Tables>
</Tables>
<Sources>
</Sources>
</DataSource>
</xs:appinfo>
</xs:annotation>
<xs:element name="dataset" msdata:IsDataSet="true"
msdata:UseCurrentLocale="true"
msprop:Generator_UserDSName="DataSet1"
msprop:Generator_DataSetName="DataSet1">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="datarow"
msprop:Generator_UserTableName="DataTable1"

msprop:Generator_RowDeletedName="DataTable1RowDeleted"
msprop:Generator_TableClassName="DataTable1DataTable"
msprop:Generator_RowChangedName="DataTable1RowChanged"
msprop:Generator_RowClassName="DataTable1Row"
msprop:Generator_RowChangingName="DataTable1RowChanging"
msprop:Generator_RowEvArgName="DataTable1RowChangeEvent"

msprop:Generator_RowEvHandlerName="DataTable1RowChangeEventHandler"
msprop:Generator_TablePropName="DataTable1"
msprop:Generator_TableVarName="tableDataTable1"
msprop:Generator_RowDeletingName="DataTable1RowDeleting">
<xs:complexType>
</xs:element>
<xs:element name="c2" minOccurs="1" >
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:maxInclusive value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
 
M

Mac

I am an idiot - RTFM as they say in the Unix world - only its a case of
FTFM in this case as its rather obscure, imho.

In the original problem I erroneously thought that the schema was
partly validating the input because exceptions were thrown when the
schema datatype was wrong (eg data is a non-number and
.....type="xs:integer"...). What is actually happening here is that the
xsd is being used to type the columns of the dataset, and when you try
to assign something to a column of the wrong type you get a Format
error exception - nothing to do with xsd validation of the xml at all.

The solution, in a sentence, is that the XmlReader argument to
dataset.readxml() must have an XmlReaderSettings object associated with
it, with its ValidationType and Schemas properties set appropriately;
optionally you can set its validationeventhandler property as well. I
discovered all this from an excellent website I'd overlooked:

http://aspalliance.com/941#Page3 which I acknowledge with thanks.

Here is the revised code, which works. The only thing I haven't figured
out is how to pick up the Line Number and Line position from the
XmlReader - if anyone can see what the commented out statement in the
error handler is doing wrong I'd appreciate - its a scoping problem of
some kind.

protected void Button1_Click(object sender, EventArgs e)
{
StreamReader SR = new StreamReader(Server.MapPath(".\\" +
"App_Code\\DataSet1.xsd"));
XmlSchema Schema = new XmlSchema();
Schema = XmlSchema.Read(SR,
new
ValidationEventHandler(ReaderSettings_ValidationEventHandler));
// 5- Create a new instance of XmlReaderSettings object
XmlReaderSettings ReaderSettings = new XmlReaderSettings();
// 6- Set ValidationType for XmlReaderSettings object
ReaderSettings.ValidationType = ValidationType.Schema;

// 7- Add Schema to XmlReaderSettings Schemas collection
ReaderSettings.Schemas.Add(Schema);
// 8- Add your ValidationEventHandler address to
// XmlReaderSettings ValidationEventHandler
// Leave out this step to use default error handler
ReaderSettings.ValidationEventHandler +=
new
ValidationEventHandler(ReaderSettings_ValidationEventHandler);
XmlReader rdr = new XmlTextReader(Server.MapPath(".\\" +
"XMLfile.xml"));
XmlReader objrdr = XmlReader.Create(rdr,ReaderSettings);
DataSet dsforload = new DataSet();
dsforload.ReadXmlSchema(Server.MapPath(".\\" +
"App_Code\\DataSet1.xsd"));
dsforload.ReadXml(objrdr, XmlReadMode.Auto);
GridView1.DataSource = dsforload;
GridView1.DataBind();
}
private void ReaderSettings_ValidationEventHandler(object sender,
ValidationEventArgs args)
{
// 11- Implement your logic for each validation iteration
string strTemp;
//strTemp = "Line: " + this.objrdr.LineNumber + " - Position: "
//+ this.objrdr.LinePosition + " - " + args.Message;
strTemp = args.Message.ToString();
Label1.Text += strTemp;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top