Я работаю над проектом, в котором мне нужно генерировать файлы XML на основе вложенных XSD. например ORDER имеет ссылку на PERSON, PERSON имеет ссылку на ADDRESS и т. Д.
Я создаю экземпляр `XmlReaderSettings 'для проверки XSD, а также для проверки XML после его генерации.
Я добавил XSD в качестве ресурсов в мою сборку. Затем я создаю экземпляр XmlSchema
для каждого ресурса от самого низкого до самого высокого и добавляю его в коллекцию XmlReaderSettings.Schemas
.
Однако при попытке добавить схему, которая ссылается на другую схему, это не удается. Я получаю исключение XmlSchemaException: «Для объявления элемента должно присутствовать либо имя, либо атрибут ref.»
Я включил примеры XSD и исходного кода ниже:
ADDRESS.xsd - ссылка на PERSON.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ADDRESS.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ADDRESS" >
<xs:complexType>
<xs:sequence>
<xs:element name="ADDRESS1" type="xs:string"/>
<xs:element name="ADDRESS2" type="xs:string"/>
<xs:element name="CITY" type="xs:string"/>
<xs:element name="STATE" type="xs:string"/>
<xs:element name="ZIP" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
PERSON.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="PERSON.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="ADDRESS.xsd"/>
<xs:element name="PERSON" >
<xs:complexType>
<xs:sequence>
<xs:element name="L_NAME" type="xs:string"/>
<xs:element name="F_NAME" type="xs:string"/>
<xs:element name="Addresses">
<xs:complexType>
<xs:sequence>
<xs:element ref="ADDRESS" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Пример кода - Загрузка и проверка XSD
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using SchemaTest.Properties;
namespace SchemaTest
{
class Program
{
static void Main(string[] args)
{
// create validation settings instance
var xmlReaderSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation |
XmlSchemaValidationFlags.ReportValidationWarnings
};
xmlReaderSettings.ValidationEventHandler += SchemaValidationEventHandler;
// added XmlResourceResolver, per the accepted answer below
xMLReaderSettings.Schemas.XmlResolver = new XmlResourceResolver();
// load schemas into validation settings instance
LoadSchema(xmlReaderSettings, Resources.PERSON);
// validate schemas
xmlReaderSettings.Schemas.Compile();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private static void LoadSchema(XmlReaderSettings xmlReaderSettings, string schemaString)
{
using (var schemaStream = new MemoryStream(Encoding.Default.GetBytes(schemaString)))
{
var schema = XmlSchema.Read(schemaStream, null);
try
{
xmlReaderSettings.Schemas.Add(schema);
}
catch (Exception ex)
{
Console.WriteLine("EXCEPTION: {0}", ex.Message);
}
}
}
private static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
Console.WriteLine("{0}: {1}", e.Severity, e.Message);
}
}
}
Я не уверен, что это как-то связано с ValidationFlags
, но я попытался удалить XmlSchemaValidationFlags.ProcessSchemaLocation
и все еще получил ту же ошибку. Я также попытался передать SchemaValidationEventHandler
методу XmlSchema.Read
(вместо нуля в примере кода), и схема, кажется, создана ОК, но при попытке добавить ее в коллекцию XmlReaderSettings.Schemas
схема все равно выдает исключение.
РЕДАКТ. - 2011.11.03
Я решил эту проблему (каламбур), создав собственного потомка XmlUrlResolver
с именем XmlResourceResolver
, основываясь на примере класса XmlResolver
в принятом ответе ниже.