none
XmlSchemaValidator Problem - Element is not declared

    Question

  •  

    I am trying to get rid of XmlReader validation, and add XmlSchemaValidator in that place.

     

    My idea is to validate element by element of a Xml document rather than the entire document.

     

    But, I have hit upon a problem, and I don't seem to be able to solve it.

    On validation of an element, it always throws an error saying ANY (ex-http://wwwe.example.com/xxx:Applicant element is not declared )element is not declared. I am pretty sure my schema and the xml being passed are correct as I was using them for the XmlReader validation , and they used to work fine.

     

     

    I am not so confident about the NameTable and the XmlNameSpaceManager parameters to be passed to the XMLSchemaValidator constructor.

     

    Please see my code below and help me find what is wrong.

    Thanks,

    Babitha

     

     

     

    public class XMLElementValidator

    {

    private bool m_bResult;

    private static XmlSchemaValidator validator = null;

    StringCollection m_errors = null;

    public XMLElementValidator(string sXml, string sXsd)

    {

    m_bResult = true;

    m_errors = new StringCollection();

    if (String.IsNullOrEmpty(sXsd) && String.IsNullOrEmpty(sXml))

    throw new Exception("XMLElementValidator:XMLElementValidator Invalid parameters");

     

     

    validator = CreateValidator(sXsd);

    validator.ValidationEventHandler += new ValidationEventHandler(vReader_ValidationEventHandler);

    // Initialize the XmlSchemaValidator object.

    validator.Initialize();

    }

    public bool ValidateElement(string elemName, string NamespaceURI, ref StringCollection errors)

    {

    if (String.IsNullOrEmpty(elemName))

    throw new Exception ("XMLElementValidator:ValidateElement Invalid Parameter elemName");

    if (errors == null)

    throw new Exception("XMLElementValidator:ValidateElement Invalid Parameter errors is null");

    errors.Clear();

    m_bResult = true;

    validator.ValidateElement(elemName, NamespaceURI, null);

    validator.ValidateEndElement(null);

    if (m_bResult == false)

    {

    foreach (string s in m_errors)

    errors.Add(s);

    }

    return (m_bResult);

    }

     

    private XmlSchemaValidator CreateValidator(string sXsd)

    {

    NameTable nt = new NameTable();

    // Load the XSD

    XmlSchema Schema = null;

    StringReader sxsdReader = new StringReader(sXsd);

    Schema = XmlSchema.Read(sxsdReader, new ValidationEventHandler(SchemaValidationEventHandler));

    // Check for a failure

    if (m_bResult == false)

    {

    throw new Exception("XMLElementValidator:XMLElementValidator Invalid xsd document");

    }

    // Add the Schema to the Schema collection

    XmlSchemaSet schemaSet = new XmlSchemaSet();

    schemaSet.Add(Schema);

     

    XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);

    XmlSchemaValidationFlags flags = XmlSchemaValidationFlags.None;

    return new XmlSchemaValidator(nt, schemaSet, nsmgr, flags);

    }

    private void SchemaValidationEventHandler(object obj, System.Xml.Schema.ValidationEventArgs args)

    {

    m_bResult = false;

    //m_Errors.Add(args.Message);

    }

    // Validation for the overloaded method

    private void vReader_ValidationEventHandler(object sender, ValidationEventArgs e)

    {

    if (e.Severity == XmlSeverityType.Error)

    {

    m_bResult = false;

    m_errors.Add(e.Message);

    }

    Saturday, December 06, 2008 6:59 PM

Answers

  •  

    Apparently, I figured what the problem was. I was trying to validate a child element before the enclosing parent element was validated. In XmlSchemaValidator, you have to always validate the elements top down. The documentation is pathetic, and you hardly get any help from it. I had to figure it out myself after a lot of trial and error.

     

    But my worries didn't end there. In the ValidateEndElement call it next started complaining "Validation failed. '' is not a valid value for element X". I was calling ValidateEndElement with just a null parameter. Apparently, I need to pass the value to be validated also to this function, not a string value - a typed value! Effectively, I need to parse the Xml document myself, find the correct datatype of the data, and then pass this value to this method to validate.

     

    I have given up on XmlSchemaValidator since then. I have gone back to good old XmlDocument.Validate.Supposedly, its performance isn't great. But, I don't think I care. My xml documents do not run into Mbs.

     

    If anybody out there is trying to use XmlSchemaValidator, one word of caution - the documentation is pathetic. That is mildly putting it. You won't get any samples, or meet people who have already done it in the web. Still if you want to do it, go ahead and do it. But, just have alternative plans if in case it never worked for you!!

    Wednesday, December 10, 2008 4:16 AM

All replies

  • Can you show you Xml document and the schema you are trying to validate it against?

     

    Thanks

    Pawel

    Saturday, December 06, 2008 9:07 PM
    Moderator
  •  

    I am afraid I can't disclose that, because that is proprietary to the company product, and will compromise the company interests. But, I don't think the problem is with the xml or xsd, because the xml is generated by the serializing the class which was generated from the xsd by using the xsd.exe tool.

     

    Can you see if there is anything wrong in the way the XmlSchemaValidator is generated? Are all the parameters passed right? Is the way the NameTable and the XmlNamespaceManager created right? Is there anything else that I am missing in the code. Does the validator being a static class has anything to do with the problem?

    Sunday, December 07, 2008 6:13 AM
  •  

    Apparently, I figured what the problem was. I was trying to validate a child element before the enclosing parent element was validated. In XmlSchemaValidator, you have to always validate the elements top down. The documentation is pathetic, and you hardly get any help from it. I had to figure it out myself after a lot of trial and error.

     

    But my worries didn't end there. In the ValidateEndElement call it next started complaining "Validation failed. '' is not a valid value for element X". I was calling ValidateEndElement with just a null parameter. Apparently, I need to pass the value to be validated also to this function, not a string value - a typed value! Effectively, I need to parse the Xml document myself, find the correct datatype of the data, and then pass this value to this method to validate.

     

    I have given up on XmlSchemaValidator since then. I have gone back to good old XmlDocument.Validate.Supposedly, its performance isn't great. But, I don't think I care. My xml documents do not run into Mbs.

     

    If anybody out there is trying to use XmlSchemaValidator, one word of caution - the documentation is pathetic. That is mildly putting it. You won't get any samples, or meet people who have already done it in the web. Still if you want to do it, go ahead and do it. But, just have alternative plans if in case it never worked for you!!

    Wednesday, December 10, 2008 4:16 AM
  • Hi,

     

    I'm sorry you found the experience with XmlSchemaValidator troublesome. Could you please provide a little more detail what information you didn't find in the documentation or which section you found hard to understand? We will try to fix this.

     

    As for the second error: If your element is supposed to have a value (as defined by the schema) you need to pass that value to the validator. This can be done either by calling ValidateText (imagine you're parsing XML and when you're on the text node inside the element you would call this method), which accepts a string (untyped). Or you can specify the value when calling the ValidateEndElement, but this one is expected to be typed already. The idea is that if you have the value as a string representation you would call ValidateText (that's what the XmlDocument.Validate will call for example), but you may have the value as a typed object (you're not validating textual XML but some other data source which looks like XML), in which case you would pass it into the ValidateEndElement.

    Also note that you can call the ValidateText multiple times and the value of the element will be the concatenation of these (for example if you have text, comment, text).

     

    Thanks,

    Wednesday, December 10, 2008 2:09 PM
    Moderator