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").
Related
I am trying to convert an XML document to another by using XslCompiledTransform. But I am getting an exception with the following error message:
For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
I already set the DtdProcessing property on XmlReaderSettings to Parse.
However, I am still encountering the same exception with the same error message.
My sample code:
XslCompiledTransform xslt = new XslCompiledTransform(false);
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings() { DtdProcessing = DtdProcessing.Parse, ValidationType = ValidationType.DTD };
xmlReaderSettings.DtdProcessing = DtdProcessing.Parse;
xmlReaderSettings.ValidationType = ValidationType.DTD;
xmlReaderSettings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
using (XmlReader xsltReader = XmlReader.Create(_tesseractSettings.GetXSLTFilePath(), xmlReaderSettings))
{
xslt.Load(_tesseractSettings.GetXSLTFilePath());
xslt.Transform(inputFile, outputFile);
}
ValidationCallBack:
private static void ValidationCallBack(object sender, ValidationEventArgs e)
{
File.WriteAllText(someTxtFilePath, e.Message);
}
If it is relevant here is the document type declarations.
Input XML:
<!DOCTYPE html PUBLIC "/W3C/DTD XHTML 1.0 Transitional/EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
XSLT file:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:htm="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0" xpath-default-namespace="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" omit-xml-declaration="yes"/>
I have also tried setting DtdProcessing to DtdProcessing.Ignore and the same exception occurs. I have also tried removing the Document Type declaration element before the transformation. When I do this I no longer get the exception, however the transformation doesn't give me the output I expect. I know the issue isn't with the xslt file because the transformation still works on Oxygen or any online tester.
I have been researching the internet but with no avail.
Any help would be appreciated thank you.
DTD which stands for Document Type Definition.The purpose of a DTD is to define the structure and the legal elements and attributes of an XML document. However it is occasionally exploited by hackers to perform something known as XXE (XML External Entity) attacks.
So Microsoft basically provides three options for Dtd Processing to avoid such attacks:
Parse: Allows parsing of DTD content inside of xml file by the xml reader. However we need to set also the validation type and validation callback to report any errors/warnings.
Inline is an example from microsoft docs:
using System;
using System.Xml;
using System.Xml.Schema;
using System.IO;
public class Sample {
public static void Main() {
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationType = ValidationType.DTD;
settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack);
// Create the XmlReader object.
XmlReader reader = XmlReader.Create("itemDTD.xml", settings);
// Parse the file.
while (reader.Read());
}
// Display any validation errors.
private static void ValidationCallBack(object sender, ValidationEventArgs e) {
Console.WriteLine("Validation Error: {0}", e.Message);
}
}
Prohibit: Also the default value of DtdProcessing. Throws an exception when xml reader encounters any DTD content in xml file.
Ignore: It simply instructs the xml reader to ignore any dtd content inside of xml file and process it. As a result the output is ripped of any dtd content if present. Thus results in loss of data.
I have a problem in validating XML against XSD when the base XSD is importing some other XSDs from site. For example, for the following XSD item, it is throwing error.
<link:linkbase xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:link = 'http://www.xbrl.org/2003/linkbase' xmlns:xbrli = 'http://www.xbrl.org/2003/instance' xmlns:xlink = 'http://www.w3.org/1999/xlink' xsi:schemaLocation = 'http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd' >
Is there any solution for importing the XSD by release version of DLLs. I am using the following C# code for validating XML against the XSD. The same is working when I execute it through Visual Studio.
var schemas = new XmlSchemaSet();
schemas.Add(null, xsdFilePath);
var readerSettings = new XmlReaderSettings();
readerSettings.ValidationType = ValidationType.Schema;
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
readerSettings.Schemas.Add(schemas);
using (var xmlReader = XmlReader.Create(xmlFilePath, readerSettings))
{
while (xmlReader.Read())
{
}
}
Obviously, the parser cannot find the schema xbrl-instance-2003-12-31. From the w3 schema specs:
(xsi:schemaLocation) records the author's warrant with pairs of URI references (one for the namespace name, and one for a hint as to the location of a schema document defining names for that namespace name)
that is, the first part of your schemaLocation definition xbrl.org/2003/xbrl-instance-2003-12-31.xsd is the namespace. If the parser doesn't already know where to find the schema for such namespace, you must provide it with the location. For example:
<xs:import
namespace='xbrl.org/2003/instance'
schemaLocation='xbrl.org/2003/xbrl-instance-2003-12-31.xsd http:/xbrl.org/2003/xbrl-instance-2003-12-31.xsd'/>
I have a webservice that gets specific XML which does not have a schema specified in the file itself.
I do have XSD schemas in my project which will be used to test the obtained XML files against them.
The problem is that whatever I do the validator seems to accept the files even when they aren't valid.
The code I'm using is this (some parts omitted to make it easier):
var schemaReader = XmlReader.Create(new StringReader(xmlSchemeInput));
var xmlSchema = XmlSchema.Read(schemaReader, ValidationHandler);
var xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.Schemas.Add(xmlSchema);
xmlReaderSettings.ValidationEventHandler += ValidationHandler;
xmlReaderSettings.ValidationType = ValidationType.Schema;
xmlReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessIdentityConstraints;
xmlReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
xmlReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
using(var xmlReader = XmlReader.Create(new StringReader(xmlInput), xmlReaderSettings))
{
while (xmlReader.Read()) { }
}
// return if the xml is valid or not
I've found several solutions with an inline specified schema which work great, but with a schema specified like this (which I assume should work) I can't seem to find any.
Am I doing something wrong? Or am I just wrong in assuming this is how it should work?
Thanks!
Try adding
xmlReaderSettings.Schemas.Compile()
after
xmlReaderSettings.Schemas.Add(xmlSchema);
worked for me in that situation.
I am serializing an object in my ASP.net MVC program to an xml string like this;
StringWriter sw = new StringWriter();
XmlSerializer s = new XmlSerializer(typeof(mytype));
s.Serialize(sw, myData);
Now this give me this as the first 2 lines;
<?xml version="1.0" encoding="utf-16"?>
<GetCustomerName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
my question is,
How can I change the xmlns and the encoding type, when serializing?
Thanks
What I found that works was to add this line to my class,
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://myurl.com/api/v1.0", IsNullable = true)]
and add this to my code to add namespace when I call serialize
XmlSerializerNamespaces ns1 = new XmlSerializerNamespaces();
ns1.Add("", "http://myurl.com/api/v1.0");
xs.Serialize(xmlTextWriter, FormData, ns1);
as long as both namespaces match it works well.
The XmlSerializer type has a second parameter in its constructor which is the default xml namespace - the "xmlns:" namespace:
XmlSerializer s = new XmlSerializer(typeof(mytype), "http://yourdefault.com/");
To set the encoding, I'd suggest you use a XmlTextWriter instead of a straight StringWriter and create it something like this:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
XmlTextWriter xtw = XmlWriter.Create(filename, settings);
s.Serialize(xtw, myData);
In the XmlWriterSettings, you can define a plethora of options - including the encoding.
Take a look at the attributes that control XML serialization in .NET.
Specifically, the XmlTypeAttribute may be useful for you. If you're looking to change the default namespace for you XML file, there is a second parameter to the XmlSerializer constructor where you can define that.
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?