I am trying to deserialize a Xml Fragment. I am nearly there but it throws an error where by it does not expect the first element. An example of the XML in the stream is as follows:
<Project xmlns="http://schemas.datacontract.org/2004/07/Swissmod.Service.Model" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ClientID>1</ClientID>
<Created>2009-03-16T20:34:57.022167+00:00</Created>
<ID>22</ID>
<LastModified>2009-03-11T20:34:57.022167+00:00</LastModified>
<ProjectDescription>Description here</ProjectDescription>
<ProjectTitle>Poject title</ProjectTitle>
<UserID>5</UserID>
<Version>1234567</Version>
</Project>
I am using the following code to deserialize:
XmlSerializer serializer = new XmlSerializer(typeof(Project));
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationFlags = XmlSchemaValidationFlags.None;
settings.ValidationType = ValidationType.None;
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.IgnoreProcessingInstructions = true;
settings.NameTable = new NameTable();
settings.NameTable.Add("http://schemas.datacontract.org/2004/07/Swissmod.Service.Model");
XmlReader reader = XmlReader.Create(wresp.GetResponseStream(),settings);
Project p = (Project)serializer.Deserialize(reader);
But the above throws the following error:
There is an error in XML document (1, 2).
"<Project xmlns='http://schemas.datacontract.org/2004/07/Swissmod.Service.Model'> was not expected."
Anyone have any ideas how I can read an XML Fragment using a XML Reader?
In your Project class definition, have you tried specifying a namespace in an XmlRoot attribute?
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 ?
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);
}
}
Ho do you deserialze xml with a xmlns? Below is the simplified xml containing the xmlns attribute and it fails to deserialize with the code below. The inner exception that I keep getting is:
{"<nzb xmlns='http://www.nzb.com'> was not expected."}
Code
TextReader tr = new StreamReader("nzb.xml");
XmlReaderSettings settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Ignore };
XmlReader xmlReader = XmlReader.Create(tr, settings);
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "nzb";
xRoot.IsNullable = true;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Nzb), xRoot);
Nzb nzbFile = (Nzb)xmlSerializer.Deserialize(xmlReader);
xmlReader.Close();
Nzb Class
[XmlRoot("nzb", Namespace = "urn:http://www.nzb.com")]
public class Nzb
{
}
nzb.xml
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE nzb>
<nzb xmlns="http://www.nzb.com">
</nzb>
Your XML root attribute overrides are causing the problem in XmlSerialiser. This is already defined in the XmlRoot attribute of class Nzb. So the following will work:
XmlReader xmlReader = XmlReader.Create(tr, settings);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Nzb));
Nzb nzbFile = (Nzb)xmlSerializer.Deserialize(xmlReader);
xmlReader.Close();
However, you will need to change the Nzb XMLRoot attribute's namespace to:
[XmlRoot("nzb", Namespace = "http://www.nzb.com")]
I'm creating a schema to validate some XML, but when it comes down to actually reading in the document, I'm getting the error:
The 'http://www.w3.org/2001/XMLSchema:schemaLocation' attribute is not declared.
This is what the beginning of one of the XML files using the schema looks like.
<?xml version="1.0"?>
<envelope xsi:schemaLocation="C:\LocalPath MySchema.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema"
xmlns="http://tempuri.org/MySchema.xsd">
...
</envelope>
My validation code looks like this:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
Settings.Schemas.Add(#"http://tempuri.org/MySchema.xsd",
#"C:\LocalPath\ MySchema.xsd");
XmlReader reader = XmlReader.Create(#"C:\LocalPath\testxml\somefile.xml", settings);
xmlDoc.Load(reader);
ValidationEventHandler eventHander = new ValidationEventHandler(validationHandler);
xmlDoc.Validate(eventHander);
The namespace http://www.w3.org/2001/XMLSchema (with conventional prefix xsd or xs) is for schema documents; the schemaLocation attribute you want is in the namespace http://www.w3.org/2001/XMLSchema-instance (which has the conventional prefix xsi for "XML Schema Instance namespace").
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