I'm trying to figure out how to correct his deprecated xml schema validation code.
public static bool ValidateXml(string xmlFilename, string schemaFilename)
{
⁞
//Forward stream reading access to data
XmlTextReader forwardStream = new XmlTextReader(xmlFilename);
//deprecated way of checking agaisnt a schema -- update.
//xmlreader class.
XmlValidatingReader validation = new XmlValidatingReader(forwardStream);
validation.ValidationType = ValidationType.Schema;
//XmlReader validator = new XmlReader.Create(
XmlSchemaCollection schemas = new XmlSchemaCollection();
schemas.Add(null, schemaFilename);
validation.Schemas.Add(schemas);
⁞
you need to use XmlReader and XmlReaderSettings instead of deprecated classes. Below is an example:
// Create the XmlSchemaSet class.
XmlSchemaSet sc = new XmlSchemaSet();
// Add the schema to the collection.
sc.Add("urn:bookstore-schema", "books.xsd");
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
// Create the XmlReader object.
XmlReader reader = XmlReader.Create("booksSchemaFail.xml", settings);
// Parse the file.
while (reader.Read());
more details here: Validating XML Data with XmlReader
Related
I try to validate my xml structure, using an xml schema.
This code sample is given here : https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.validate?view=net-5.0
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
// the following call to Validate succeeds.
document.Validate(eventHandler);
// add a node so that the document is no longer valid
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToFollowing("price", "http://www.contoso.com/books");
XmlWriter writer = navigator.InsertAfter();
writer.WriteStartElement("anotherNode", "http://www.contoso.com/books");
writer.WriteEndElement();
writer.Close();
// the document will now fail to successfully validate
document.Validate(eventHandler);
Problem is that when I'm using a non valide xml document, I already have an exception of type System.Xml.Schema.XmlSchemaValidationException on line :
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
Does this mean you dont need to use this Validate(eventHandler) method with C# 6 anymore ? Or will it take care of few specific validation problems ?
Rule:
Do not allow Dtd on XmlTextReader
Category:
Microsoft.Security.Xml
Check Id:
CA3054
Rule Description:
Prohibit DTD processing when using XmlTextReader on untrusted sources. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for
the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.
Rule File:
securityxmlrules.dll [14.0.0.0]
Help:
http://go.microsoft.com/fwlink/?LinkId=282614&clcid=0x409
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
StringReader stringReader = new StringReader(xml);
XmlTextReader reader = new XmlTextReader(stringReader);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
XmlAttributeCollection attrs = doc.DocumentElement.Attributes;
if (!string.IsNullOrWhiteSpace(cookie))
{
string pagingcookie = GetPagingCookie(cookie);
if (!string.IsNullOrWhiteSpace(pagingcookie))
{
XmlAttribute pagingAttr = doc.CreateAttribute("paging-cookie");
pagingAttr.Value = pagingcookie;
attrs.Append(pagingAttr);
}
}
How to resolve this FxCop for SDL
You created a settings object but your XmlReader doesn't actually use it. You need to create an XmlReader with the settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
StringReader stringReader = new StringReader(xml);
XmlReader reader = XmlReader.Create(stringReader, settings);
I would like to cache the xsd then perform validation against it rather than loading xsd every time for any xml in order to increase performance. However, I could not manage to do it. My guess is that the compilation does not add the include and import elements of the xsd files that is why I get the error below.
Here are the steps:
First I added the xsd file to XmlSchemaSet
public XmlSchemaSet SchemaSet;
public XmlValidator()
{
this.SchemaSet = new XmlSchemaSet();
using (XmlReader xsd = XmlReader.Create(xsdPath))
{
this.SchemaSet.Add(null, xsd);
}
this.SchemaSet.Compile();
}
Then I used this XmlSchemaSet to validate the xml as follows:
public void ValidateSchema(byte[] xml)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationType = ValidationType.Schema;
settings.DtdProcessing = DtdProcessing.Parse;
// need to add dtd first. it should not be added to the schema set above
using (XmlReader dtd = XmlReader.Create(dtdPath, settings))
{
settings.Schemas.Add(null, dtd);
}
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.Schemas.Add(this.SchemaSet); // add the schema set
using (MemoryStream memoryStream = new MemoryStream(xml, false))
{
using (XmlReader validator = XmlReader.Create(memoryStream, settings))
{
while (validator.Read());
}
}
}
Notes: dtdPath, xsdPath are valid, input xml is valid, xsd files are valid
The error is:
The'http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader:StandardBusinessDocument' element is not declared.
I created a XmlReaderSettings with following options:
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = new XmlXsdResolver(); // Need this for resolving include and import
settings.ValidationType = ValidationType.Schema; // This might not be needed, I am using same settings to validate the input xml
settings.DtdProcessing = DtdProcessing.Parse; // I have an include that is dtd. maybe I should prohibit dtd after I compile the xsd files.
Then I used it with an XmlReader to read the xsd. The important part is that I had to put a basePath so that the XmlXsdResolve can find other xsd files.
using (XmlReader xsd = XmlReader.Create(new FileStream(xsdPath, FileMode.Open, FileAccess.Read), settings, basePath))
{
settings.Schemas.Add(null, xsd);
}
settings.Schemas.Compile();
This is the XmlXsdResolver to find included and imported xsd files:
protected class XmlXsdResolver : XmlUrlResolver
{
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
The following XML validation only works on my local computer. When I run the same validation on our test server I get the error message: "simpleType 'schemaversion' has already been declared". Why?
XmlSchema schemaSimpleTypes = GetXmlSchemaFromContractAssembly(assemblyContract, "SimpleTypes");
XmlSchema schemaCommonTypes = GetXmlSchemaFromContractAssembly(assemblyContract, "CommonTypes");
XmlSchema schemaMessageType = GetXmlSchemaFromContractAssembly(assemblyContract, messageType);
// Set the validation settings
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
settings.Schemas.Add(schemaSimpleTypes);
settings.Schemas.Add(schemaCommonTypes);
settings.Schemas.Add(schemaMessageType);
// Create the XmlReader object
XmlReader reader = XmlReader.Create(DataConversion.ConvertUtf8StringToStream(xmlDoc.OuterXml), settings);
// Parse the file.
while (reader.Read())
{
// go through XML, validating against XSD
// exceptions are passed to the calling method
};
reader.Close();
When I perform the validation without "schemaSimpleTypes" and "schemaCommonTypes", then it does work on the server but not on the local computer and I get following error on the local comupter : "The type 'schemaversion' is not a simple type or has not been declared . "
Here's the code:
XmlSchema schemaSimpleTypes = GetXmlSchemaFromContractAssembly(assemblyContract, "SimpleTypes");
XmlSchema schemaCommonTypes = GetXmlSchemaFromContractAssembly(assemblyContract, "CommonTypes");
XmlSchema schemaMessageType = GetXmlSchemaFromContractAssembly(assemblyContract, messageType);
// Set the validation settings
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
//settings.Schemas.Add(schemaSimpleTypes);
//settings.Schemas.Add(schemaCommonTypes);
settings.Schemas.Add(schemaMessageType);
// Create the XmlReader object
XmlReader reader = XmlReader.Create(DataConversion.ConvertUtf8StringToStream(xmlDoc.OuterXml), settings);
// Parse the file.
while (reader.Read())
{
// go through XML, validating against XSD
// exceptions are passed to the calling method
};
reader.Close();
What is the problem here?
I did generate C# class form scham using xsd.exe (VS 2010 command prompt),
but when I serialize class to xml file, in the out file I don't have entry for schema.
Serialized xml:
<?xml version="1.0" encoding="utf-16"?>
<Dokumenty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" idSystemuLokalnego="ASD" dataUtworzenia="0001-01-01T00:00:00">
<Wniosek>
<Beneficjent />
</Wniosek>
When I try to validate with schema using code:
//Serilalize xml to string
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
x.Serialize(xw, doc);
String xml = sw.ToString();
StringReader sr = new StringReader(xml);
XmlTextReader xtr = new XmlTextReader(sr);
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("", "schemas\\SimWniosekApl_v2.0.xsd");
settings.ValidationType = ValidationType.Schema;
//XmlReader reader = XmlReader.Create(xtr);
XmlDocument document = new XmlDocument();
document.Load(xtr);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationHandler);
// the following call to Validate succeeds.
document.Validate(eventHandler);
It fails with exception:
Additional information: The XmlSchemaSet on the document is either null or has no schemas in it. Provide schema information before calling Validate.
What do I do wrong?
you need to apply the XmlReaderSettings when you create the reader.
That code does nothing with the settings. The reader has been created already, before the settings are created. The code simply creates settings and then forgets them.
StringReader sr = new StringReader(xml);
//XmlTextReader xtr = new XmlTextReader(sr);
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("", "schemas\\SimWniosekApl_v2.0.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create(xtr,settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationHandler);
document.Validate(eventHandler);
There is a full example here:
http://msdn.microsoft.com/en-us/library/ms162371.aspx