I am using following code to validate XML agains the XSD:
public static bool IsValidXmlOld(string xmlFilePath, string xsdFilePath)
{
if (File.Exists(xmlFilePath) && File.Exists(xsdFilePath))
{
try
{
XDocument xdocXml = XDocument.Load(xmlFilePath);
var schemas = new XmlSchemaSet();
schemas.Add(null, xsdFilePath);
Boolean result = true;
xdocXml.Validate(schemas, (sender, e) =>
{
result = false;
});
return result;
}
catch (Exception ex)
{
// Logging logic + error handling logic
throw new Exception(ex.Message);
}
}
throw new Exception("Either the Schema or the XML file does not exist Please check");
}
For some reason, it always returns true even if the XML is not valid for given XSD. I picked up this code from following link:
Validate XML against XSD in a single method. sounds like that result= false never gets called even if the xml is completely invalid.
I have a pair of valid and invalid XML that goes against a particular XSD
Valid XML
XSD
Invalid XML
If I try to validate them on This web site then the valid one passes the validation test against the invalid one BUT the invalid XML Fails the test. However, the code above passes both the XMLs invariably.
At the same time it fails the validation when I use some basic XML like following:
XDocument doc2 = new XDocument(
new XElement("Root",
new XElement("Child1", "content1"),
new XElement("Child3", "content1")
)
);
with following error:
The 'Root' element is not declared.: {0}
Now, it clearly demonstrates that the code is not completely incapable of failing a validation. However, what is so special about the 3. Invalid XML that the code passes that particular XML when This Site clearly fails it?
Related
I have a c# script that validates an XML document against an XSD document, as follows:
static bool IsValidXml(string xmlFilePath, string xsdFilePath)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(null, xsdFilePath);
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Compile();
try
{
XmlReader xmlRead = XmlReader.Create(xmlFilePath, settings);
while (xmlRead.Read())
{ };
xmlRead.Close();
}
catch (Exception e)
{
return false;
}
return true;
}
I've compiled this after looking at a number of MSDN articles and questions here where this is the solution. It does correctly validate that the XSD is formed well (returns false if I mess with the file) and checks that the XML is formed well (also returns false when messed with).
I've also tried the following, but it does the exact same thing:
static bool IsValidXml(string xmlFilePath, string xsdFilePath)
{
XDocument xdoc = XDocument.Load(xmlFilePath);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, xsdFilePath);
try
{
xdoc.Validate(schemas, null);
}
catch (XmlSchemaValidationException e)
{
return false;
}
return true;
}
I've even pulled a completely random XSD off the internet and thrown it into both scripts, and it still validates on both. What am I missing here?
Using .NET 3.5 within an SSIS job.
In .NET you have to check yourself if the validator actually matches a schema component; if it doesn't, there is no exception thrown, and so your code will not work as you expect.
A match means one or both of the following:
there is one global element in your schema set with a qualified name that is the same as your XML document element's qualified name.
the document element has an xsi:type attribute, that is a qualified name pointing to a global type in your schema set.
In streaming mode, you can do this check easily. This pseudo-kind-of-code should give you an idea (error handling not shown, etc.):
using (XmlReader reader = XmlReader.Create(xmlfile, settings))
{
reader.MoveToContent();
var qn = new XmlQualifiedName(reader.LocalName, reader.NamespaceURI);
// element test: schemas.GlobalElements.ContainsKey(qn);
// check if there's an xsi:type attribute: reader["type", XmlSchema.InstanceNamespace] != null;
// if exists, resolve the value of the xsi:type attribute to an XmlQualifiedName
// type test: schemas.GlobalTypes.ContainsKey(qn);
// if all good, keep reading; otherwise, break here after setting your error flag, etc.
}
You might also consider the XmlNode.SchemaInfo which represents the post schema validation infoset that has been assigned to a node as a result of schema validation. I would test different conditions and see how it works for your scenario. The first method is recommended to reduce the attack surface in DoS attacks, as it is the fastest way to detect completely bogus payloads.
I am Having a sring for which i need to chek weather it has correct XML format like consistent start and end tags.
Sorry i tried to make string value well formated but could not :).
string parameter="<HostName>Arasanalu</HostName><AdminUserName>Administrator</AdminUserName><AdminPassword>A1234</AdminPassword><placeNumber>38</PlaceNumber>"
I tried with following check :
public bool IsValidXML(string value)
{
try
{
// Check we actually have a value
if (string.IsNullOrEmpty(value) == false)
{
// Try to load the value into a document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(parameter);
// If we managed with no exception then this is valid XML!
return true;
}
else
{
// A blank value is not valid xml
return false;
}
}
catch (System.Xml.XmlException)
{
return false;
}
}
It was throwing error for correct as well as wrong format.
Please let me know how can i proceed.
Regards,
Channa
The content of the string you have do not actually form a valid xml document
Its missing a Root Element
string parameter="<HostName>Arasanalu</HostName><AdminUserName>Administrator</AdminUserName><AdminPassword>A1234</AdminPassword><PlaceNumber>38</PlaceNumber>";
XmlDocument doc = new XmlDocument(); \
doc.LoadXml("<root>" + parameter + "</root>"); // this adds a root element and makes it Valid
Root Element
There is exactly one element, called the root, or document element, no
part of which appears in the content of any other element.] For all
other elements, if the start-tag is in the content of another element,
the end-tag is in the content of the same element. More simply stated,
the elements, delimited by start- and end-tags, nest properly within
each other.
Always put proper tags in variable. Put <root> tag before and after you code. Try below code.
try
{
string unformattedXml = "<Root><HostName>Arasanalu</HostName><AdminUserName>Administrator</AdminUserName><AdminPassword>A1234</AdminPassword><PlaceNumber>38</PlaceNumber></Root>";
string formattedXml = XElement.Parse(unformattedXml).ToString();
return true;
}
catch (Exception e)
{
return false;
}
I need to implement a C# method that needs to validate an XML against an external XSD and return a Boolean result indicating whether it was well formed or not.
public static bool IsValidXml(string xmlFilePath, string xsdFilePath);
I know how to validate using a callback. I would like to know if it can be done in a single method, without using a callback. I need this purely for cosmetic purposes: I need to validate up to a few dozen types of XML documents so I would like to make is something as simple as below.
if(!XmlManager.IsValidXml(
#"ProjectTypes\ProjectType17.xml",
#"Schemas\Project.xsd"))
{
throw new XmlFormatException(
string.Format(
"Xml '{0}' is invalid.",
xmlFilePath));
}
There are a couple of options I can think of depending on whether or not you want to use exceptions for non-exceptional events.
If you pass a null as the validation callback delegate, most of the built-in validation methods will throw an exception if the XML is badly formed, so you can simply catch the exception and return true/false depending on the situation.
public static bool IsValidXml(string xmlFilePath, string xsdFilePath, XNamespace namespaceName)
{
var xdoc = XDocument.Load(xmlFilePath);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
try
{
xdoc.Validate(schemas, null);
}
catch (XmlSchemaValidationException)
{
return false;
}
return true;
}
The other option that comes to mind pushes the limits of your without using a callback criterion. Instead of passing a pre-defined callback method, you could instead pass an anonymous method and use it to set a true/false return value.
public static bool IsValidXml(string xmlFilePath, string xsdFilePath, XNamespace namespaceName)
{
var xdoc = XDocument.Load(xmlFilePath);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
Boolean result = true;
xdoc.Validate(schemas, (sender, e) =>
{
result = false;
});
return result;
}
I got this weird error when I wanted to validate my in-memory xml Schema, anything I did wrong?
[Test]
public void ValidationXML()
{
int errorCount = 0;
var xmlString = "<?xml version='1.0'?><response><error code='1'> Success</error></response>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlString);
xmlDocument.Validate((sender, e) => errorCount++);
Assert.AreEqual(0, errorCount);
}
The exception was:
failed: System.InvalidOperationException : The XmlSchemaSet on the document is either null or has no schemas in it. Provide schema information before calling Validate.
at System.Xml.XmlDocument.Validate(ValidationEventHandler validationEventHandler, XmlNode nodeToValidate)
at System.Xml.XmlDocument.Validate(ValidationEventHandler validationEventHandler)
You are trying to validate the XmlDocument without assigning a schema to check against.
xmlDocument.Schemas.Add(new XmlSchema());
This tries to validate against an empty schema (as opposed to null) and will fail the validation (instead of throwing an exception), setting errorCount to 1.
Im trying to validate an XML file using a .DTD but it gives me the following error.
'ENTITY' is an unexpected token. The expected token is 'DOCTYPE'. Line 538, position 3.
public static void Validate(string xmlFilename, string schemaFilename)
{
XmlTextReader r = new XmlTextReader(xmlFilename);
XmlValidatingReader validator = new XmlValidatingReader(r);
validator.ValidationType = ValidationType.Schema;
XmlSchemaCollection schemas = new XmlSchemaCollection();
schemas.Add(null, schemaFilename);
validator.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
try
{
while (validator.Read())
{ }
}
catch (XmlException err)
{
Console.WriteLine(err.Message);
}
finally
{
validator.Close();
}
}
The DTD im using to validate = http://www.editeur.org/onix/2.1/reference/onix-international.dtd
I hope someone can help me thanks!
I realise this is a really old question, but for anyone else struggling with this problem, here's what I did.
I gave up trying to validate with the DTD.
Instead, I ended up using the onix 2.1 xsd available at http://www.editeur.org/15/Previous-Releases/#R%202.1%20Downloads. I had to set the default namespace:
var nt = new NameTable();
var ns = new XmlNamespaceManager(nt);
ns.AddNamespace(string.Empty, "http://www.editeur.org/onix/2.1/reference");
var context = new XmlParserContext(null, ns, null, XmlSpace.None);
and then when loading the xml, turn off DTD parsing (this is using .NET4)
var settings = XmlReaderSettings
{
ValidationType = System.Xml.ValidationType.Schema,
DtdProcessing = DtdProcessing.Ignore
}
using(var reader = XmlReader.Create("path to xml file", settings)) { ... }
Edit:
Just noticed: your validation type is also set wrong. Try setting it to ValidationType.DTD instead of Schema.
ValidationType at MSDN
--
The error means exactly as it states- the DTD that is referenced is not well formed, as DOCTYPE should be present before any other declarations in a DTD.
Document Type Definition (Wikipedia)
Introduction to DTD (w3schools)
You might be able to get around this by downloading a local copy, modifying it to add in the expected root element yourself, and then referencing your edited version in your source.