简体   繁体   中英

C# Deserializing, and validating an XML file against an XSD using XmlReader.Create isn't working

I am using Visual Studio 2015. I apologize for the poorly named "firstName" element. It should have been "fullName", but since I already generated the class for the schema, and this is just for my own learning, I left it as is. I have an XML schema here:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="address-schema"
targetNamespace="http://tempuri.org/address-schema.xsd"
elementFormDefault="qualified"
attributeFormDefault="qualified"
xmlns:addr="http://tempuri.org/address-schema.xsd"
xmlns:mstns="http://tempuri.org/address-schema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="address">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstName">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="first" type="addr:nameComponent"/>
              <xs:element name="middle" type="addr:nameComponent" minOccurs="0"/>
              <xs:element name="last" type="addr:nameComponent"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="nameComponent">
    <xs:simpleContent>
      <xs:extension base="xs:string"/>
    </xs:simpleContent>
  </xs:complexType>

</xs:schema>

And an XML file that I think conforms to the schema:

<?xml version="1.0" encoding="utf-8" ?>
<addr:address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://tempuri.org/address-schema.xsd address-schema.xsd" 
          xmlns:addr="http://tempuri.org/address-schema.xsd">
  <addr:firstName>
    <addr:first>Some</addr:first>
    <addr:middle>Bodys</addr:middle>
    <addr:last>Name</addr:last>
  </addr:firstName>
</addr:address>

And the code that is attempting to validate the XML is here (note that the "address" class that the XML file is getting deserialized into is an auto generated class from xsd.exe):

address address;
var xmlSchemaSerializer = new XmlSerializer(typeof(XmlSchema));
var addressXmlSerializer = new XmlSerializer(typeof(address));

var schemas = new XmlSchemaSet();
XmlSchema schema;
using (var xsdStream = File.OpenRead("address-schema.xsd"))
{
    schema = (XmlSchema)xmlSchemaSerializer.Deserialize(xsdStream);
}
schemas.Add(schema);
var settings = new XmlReaderSettings
{
    Schemas = schemas,
    ValidationType = ValidationType.Schema,
    ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation
};
settings.ValidationEventHandler += (sender, arguments) =>
{
    throw new XmlSchemaValidationException(arguments.Message);
};

using(Stream addressXmlStream = File.OpenRead("address-doc.xml"))
using (XmlReader reader = XmlReader.Create(addressXmlStream, settings))
{
    address = (address)addressXmlSerializer.Deserialize(reader);
}
Console.WriteLine(address.firstName.first.Value == "Some" ? "Success!" : "Fail");
Console.ReadKey();

The exception ('System.Xml.Schema.XmlSchemaValidationException'The global element ' http://tempuri.org/address-schema.xsd:address ' has already been declared.) is thrown in the ValidationEventHandler. Any help or suggestions would be appreciated. Thanks in advance!

The cause of your exception is that your document has a schema location hint that loads the schema, but you've already loaded it.

Either don't pre-load the schema or remove the xsi:schemaLocation attribute from your document.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM