XmlReaderSettings does not resolve an xs:import with http://... location

Answered XmlReaderSettings does not resolve an xs:import with http://... location

  • 2008年10月16日 20:44
     
     

     

    Hi,

    I'm trying to validate an Xml document using an XmlReader. Here is my code:

     

    private void Validate(TextReader source, string xsd)

    {

    XmlReaderSettings settings = new XmlReaderSettings();

    XmlUrlResolver resolver = new XmlUrlResolver();

    settings.ProhibitDtd = false;

    resolver.Credentials = CredentialCache.DefaultCredentials;

    settings.XmlResolver = resolver;

    settings.ValidationFlags = XmlSchemaValidationFlags.ProcessSchemaLocation;

    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;

    settings.Schemas.XmlResolver = resolver;

    settings.Schemas.Add(null, xsd);

    settings.Schemas.Compile();

    //settings.Schemas.Add(null, http://www.w3.org/2001/xml.xsd);

    settings.ValidationType = ValidationType.Schema;

    settings.ValidationEventHandler += ValidationHandler;

    XmlReader reader = XmlReader.Create(source, settings);

    while (reader.Read())

    {

    }

     

    }

     

    The xsd of the xml document I want to validate contains an xs:import that points to local xsd (the schemaLocation is, as example "./dc.xsd"). This xsd imports serveral other xsd, one of which is the following:

     

    <xs:import namespace="http://www.w3.org/XML/1998/namespace"
                 schemaLocation="http://www.w3.org/2001/03/xml.xsd">
      </xs:import>

     

    When settings.Schemas.Add(null,xsd) is executed, all nested LOCAL xsd are correctly resolved by the XmlUrlResolver I created. If i inspect during debug my XmlReaderSetting instance i can see tha all the required xsd are correctly loaded, EXCEPT http://www.w3.org/2001/03/xml.xsd. Then settings.Schemas.Compile() is executed, an exception  is raised telling me that the attribute xml:lang is not defined (it's defined in the missing xsd).

    This exception is not raised, and validaion is performed correctly, if i manually add the namespace (see the commented line of my code), or if i change the scema location in the xsd file to point to a local copy of xml.xsd (schemaLocation="./xml.xsd").

     

    I would like to know how can I make this work, because i don't want to add manually anything related to this specific scenario (i.e. i would like to reuse the code). In other words, why this remote location is not resolved?

     

     

全部回复

  • 2008年10月17日 16:30
     
     已答复

    http://www.w3.org/2001/03/xml.xsd references a DTD so it might not be loaded as .NET 2.0 and later by default regards DTDs as a security risk. I would expect however that you would get an error. Nevertheless try whether changing your code to the below helps:

    Code Snippet

    XmlReaderSettings settings = new XmlReaderSettings();

    XmlUrlResolver resolver = new XmlUrlResolver();

    settings.ProhibitDtd = false;

    resolver.Credentials = CredentialCache.DefaultCredentials;

    settings.XmlResolver = resolver;

    settings.ValidationFlags = XmlSchemaValidationFlags.ProcessSchemaLocation;

    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;

    settings.Schemas.XmlResolver = resolver;

     

    XmlReaderSettings schemaSettings = new XmlReaderSettings();

    schemaSettings.ProhibitDtd = false;

     

    settings.Schemas.Add(null, XmlReader.Create(xsd, schemaSettings));

     

    settings.Schemas.Compile();

    //settings.Schemas.Add(null, http://www.w3.org/2001/xml.xsd);

    settings.ValidationType = ValidationType.Schema;

    settings.ValidationEventHandler += ValidationHandler;

    XmlReader reader = XmlReader.Create(source, settings);

    while (reader.Read())

    {

    }

     

     

  • 2008年10月17日 20:29
     
     

     

    Thank you very much for your help, now it seems to work...but my troubles are not yet finished. You mentioned that http://www.w3.org/2001/03/xml.xsd refers to a DTD, in the DOCTYPE part.

    This at first seemed a little strange to me, cause my local copy does not contain that reference. I simply cut and pasted what my browser showed me on that url. But, after a deeper look into the source page (i.e. what really the document is) i saw that reference and i realized that i didn't pasted the doctype part before. Now, your fixed code can resolve the remote url correctly (http://..), but now it's the local reference (./xml.xsd) that is not resolved anymore (and my old version is unable as well).

    If i delete the DOCTYPE part from the local copy, then all works correctly.

    Is it possible to make it work even with DOCTYPE header?

     

    Thank you in advance for your kindness.

     

  • 2008年10月18日 11:39
     
     已答复

    If you want to copy everything locally then you need to make sure you copy all external entities too. So you need xml.xsd, you need XMLSchema.dtd, and you need datatypes.dtd (which is referenced from XMLSchema.dtd).

    So without more information I can only assume that you did not copy everything you need. If you still have problems then tell us the exact error message you get.

  • 2008年10月18日 11:43
     
     
    Forget all this, I managed what was wrong. What I missed was that in the last case (i.e. working with local xml.xsd) requires that the referenced DTD must be in the same path as well. I think it's required cause in the doctype header there is no complete URI, but only a relative one, and then XmlUrlResolver tries to get the dtd from the same path of xml.xsd.

     

  • 2008年10月18日 11:50
     
     

    How funny!! We reply in the same time (you 23.39 - me 23.43). Yes you are right, i needed the dtd as well.

    Now all works. Thank you again for your time and help, it has been very precious

  • 2012年3月5日 8:36
     
      包含代码

    I ran into the exact same issue, but I have not yet managed to get it to work. I am trying to validate against an xliff schema, which imports xml.xsd. I copied all schemas and dtds, but I still cannot get it to validate. My code is as follows:

    // Create a simple test document
    XmlDocument doc = new XmlDocument();
    doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));
    XmlElement root = doc.CreateElement("xliff");
    root.SetAttribute("version", "1.2");
    doc.AppendChild(root);
    
    XmlReaderSettings xrs = new XmlReaderSettings();
    xrs.DtdProcessing = DtdProcessing.Parse;
    xrs.ValidationType = ValidationType.Schema;
    
    XmlUrlResolver resolver = new XmlUrlResolver() { Credentials = CredentialCache.DefaultCredentials };
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.DtdProcessing = DtdProcessing.Parse;
    settings.XmlResolver = resolver;
    settings.ValidationFlags =
      XmlSchemaValidationFlags.ReportValidationWarnings |
      XmlSchemaValidationFlags.ProcessSchemaLocation;
    
    settings.Schemas.XmlResolver = resolver;
    
    settings.ValidationType = ValidationType.Schema;
    
    settings.ValidationEventHandler += ValidationHandler;
    
    settings.Schemas.Add(null, XmlReader.Create("./xliff-core-1.2-strict.xsd", xrs));
    
    settings.Schemas.Compile();
    
    StringReader sr = new StringReader(doc.OuterXml);
    XmlReader reader = XmlReader.Create(sr, settings);
    
    while (reader.Read()) ;

    I altered the header of the xliff document to remove the reference to the w3.org site:

    <xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
      <!-- Import for xml:lang and xml:space -->
      <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="./xml.xsd"/>

    The header of xml.xsd is as follows:

    <!DOCTYPE xs:schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "XMLSchema.dtd" >
    <xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">

    The files xliff-core-1.2-strict.xsd, xml.xsd, XMLSchema.dtd and datatypes.dtd are all copied to the Debug folder. However, when I run my code, I get the warning: Could not find schema information for the element 'xliff'.

    This is strange, since this element is the root element of the xliff document..

    Any idea what I am doing wrong?