Get noNameSpaceSchemaLocation from xml file - c#

I'm trying to read a xml-file with it's schema.
My xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<PersonList
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="D:\MySchema.xsd">
Now I'm reading the xml file like this:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
using (XmlReader reader = XmlReader.Create("MyXmlFile.xml", settings))
{
while(reader.Read())
//.....
}
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}
The problem is that when the schema 'D:\MySchema.xsd' is not found, it's still reading the xml so noNamespaceSchemaLocation is useless...
So I've set the Schema path in my code like this:
settings.Schemas.Add(null, "D:\\MySchema.xsd");
And now it's reading the xml file by using the schema, but I'm setting here the schema path hardcoded...
I want to get the schema path (noNamespaceSchemaLocation) from the xml file and add the schema to the settings depending on the schema from the xml file. By doing it like this, I can also check if the Schema exists or not.
To make it clear: How can I get the noNamespaceSchemaLocation from a xml file?

xsi:noNamespaceSchemaLocation="anyURI"
You probably need to specify the location as a uri, so something like file://d:/myschema.xsd

Why can't the framework load the value of noNamespaceSchemaLocation attribute as it is the standard attribute defined for the class? Could be an enhancement to XML library to load the noNamespaceSchemaLocation attribute value to some property under Schemas so that it will be easier for developer to extract the value and check if the file exists or not and proceed to validate the Xml.

Related

C# validate a xml vs. xsd using XmlReader; How to fix following error without changing the xsd

I am trying to validate a xml file againg a xsd, but for some reason the following Errorr occures.
Strange is that different programms, which do the same does not show an error.
How can i change the settings for the xsd to not check for missing attributes and just ignore them?
Code:
static void ValidateXml(string xmlFile, string xsdFile)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, xsdFile);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += ValidationEventHandler;
using (XmlReader reader = XmlReader.Create(xmlFile, settings)) // failing here
{
while(reader.Read())
{
// Reading and doing nothing with the xml file.
}
}
}
Error Message:
System.Xml.Schema.XmlSchemaValidationException: "The 'http://www.w3.org/XML/1998/namespace:lang' attribute is not declared."
I tried it using XMlDocument, but that doesnt work for me, cause i am reading of xml files up to 2 gb.

C# Validate XML file using a DTD file without the DOCTYPE string

I am trying to write a C# class that validates a xml file using a DTD file located in another folder that is not in a relative location with the DOCTYPE string, so far, my code is like this:
var settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationType = ValidationType.DTD;
settings.XmlResolver = new XmlUrlResolver();
settings.ValidationEventHandler += new ValidationEventHandler(IsLoaded);
using (var reader = XmlReader.Create(new StringReader(xmlString), settings))
{
while (reader.Read()) { }
reader.Close();
}
So far this works fine loading the DTD file from the DOCTYPE string included in the xml file, but the DTD file itself must be kept in a folder that is relative to where the program is being excuted. Is there a way to mingle with the XmlResolver class where I can ask it to get a DTD file from another location on my hard drive, like an absoute path being passed in the find the DTD files instead of using the DOCTYPE string?

How to validate xml, not containing xmlns=..., with c# XmlSerializer?

I am working with Mismo 2.3.1, dtd based schema. I converted the dtd to xsd and then generated c# code to serialize/deserialze object representations of the xml doc.
Given a valid mismo 2.3.1 xml doc, I can deserialize into my generated C# class.
I have code working to use XmlSerializer along with XmlReaderSettings and XmlSchmeas collection, reading in my converted xsd.
If I put xmlns="http://mySchema..." in the root element, and try to validate intentionally invalid xml, works as expected, my validation event gets pinged with accurate description.
If I take out the xmlns attribute, then i get "could not find schema information for element [my root element]"
Any idea on how to validate xml that comes in without the xmlns spec? Any settings to say to the serializer "use this schema when you come across this element"?
Thanks in advance!
static void Main() {
var settings = new XmlReaderSettings();
settings.NameTable = new NameTable();
var nsMgr = new XmlNamespaceManager(settings.NameTable);
nsMgr.AddNamespace("", "http://example.com/2013/ns"); // <-- set default namespace
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, #"C:\XSDSchema.xsd"); // <-- set schema location for the default namespace
var parserCtx = new XmlParserContext(settings.NameTable, nsMgr, XmlSpace.Default);
using (var reader = XmlReader.Create(#"C:\file.xml", settings, parserCtx)) {
var serializer = new XmlSerializer(typeof(Foo));
Foo f = (Foo)serializer.Deserialize(reader);
}
}

Validate xml against dtd from string

I have an xml file that refers to a local dtd file. But the problem is that my files are being compressed into a single file (I am using Unity3D and it puts all my textfiles into one binary). This question is not Unity3D specific, it is useful for anyone that tries to load a DTD schema from a string.
I have thought of a workaround to load the xml and load the dtd separately and then add the dtd file to the XmlSchemas of my document. Like so:
private void ReadConfig(string filePath)
{
// load the xml file
TextAsset text = (TextAsset)Resources.Load(filePath);
StringReader sr = new StringReader(text.text);
sr.Read(); // skip BOM, Unity3D catch!
// load the dtd file
TextAsset dtdAsset = (TextAsset)Resources.Load("Configs/condigDtd");
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(...); // my dtd should be added into this schemaset somehow, but it's only a string and not a filepath.
XmlReaderSettings settings = new XmlReaderSettings() { ValidationType = ValidationType.DTD, ProhibitDtd = false, Schemas = schemaSet};
XmlReader r = XmlReader.Create(sr, settings);
XmlDocument doc = new XmlDocument();
doc.Load(r);
}
The xml starts like this, but the dtd cannot be found. Not strange, because the xml file was loaded as a string, not from a file.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Scene SYSTEM "configDtd.dtd">
XmlSchema has a Read method that takes in a Stream and a ValidationEventHandler. If the DTD is a string, you could convert it to a stream
System.Text.Encoding encode = System.Tet.Encoding.UTF8;
MemoryStream ms = new MemoryStream(encode.GetBytes(myDTD));
create the XmlSchema
XmlSchema mySchema = XmlSchema.Read(ms, DTDValidation);
add this schema to the XmlDocument containing the xml you are validating
myXMLDocument.Schemas.Add(mySchema);
myXMLDocument.Schemas.Compile();
myXMLDocument.Validate(DTDValidation);
The DTDValidation() handler would contain code handling what to do if the xml is invalid.

Confused about XmlSerializer + schemaLocation

I am having trouble validating serialized data.
Ok, so I started with an XSD file which I got from some third party. Generated C# classes using xsd tool. Then I added
[XmlAttribute("noNamespaceSchemaLocation", Namespace = System.Xml.Schema.XmlSchema.InstanceNamespace)]
public string SchemaLocation = "http://localhost/schemas/AP_Transactions_10052011.xsd";
to the top level object. The URL in question is obviously accessible from my machine where I am running the code. Then I am serializing it using XmlSerializer, which correctly produces
<?xml version="1.0" encoding="utf-8"?>
<BU_AP_Vendor_Invoices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="http://local.com/schemas/AP_Transactions_10052011.xsd">
...
</BU_AP_Vendor_Invoices>
So far so good.
Now I am trying to validate the file like so:
public static void Validate(TextReader xmlData)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += delegate(object sender, ValidationEventArgs args)
{
Console.WriteLine(args.Message);
};
using (XmlReader xmlReader = XmlReader.Create(xmlData, settings))
while (xmlReader.Read()) ;
}
Which results Could not find schema information for the element 'element name' warnings for every element in the XML file. I assume that means the XSD is simply not being loaded.
I was looking at the XmlReaderSettings.Schemas, but how would the reader know what to add there? I assumed that if I don't add schemas explicitly then magic will simply happen, but that doesn't seem to work.
Question is how to do this properly?
Please take a look at this post; the gist is to use XmlSchemaValidationFlags.ProcessSchemaLocation.

Categories