Использование .NET для проверки XML по схеме

Я хочу проверить (правда или ложь), соответствует ли произвольный файл XML заданной схеме.

Что бы это ни стоило, схема — это схема Word 2003 WordML, которую Microsoft определяет, используя список примерно из 7 *.xsd файлов.

Один из этих файлов также включает в себя файл W3C xml.xsd, содержащий следующую инструкцию:

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

Для проверки я использую код .NET, подобный следующему:

   public static void validate(string filename)
    {
       XmlReaderSettings settings = new XmlReaderSettings();
       settings.Schemas.Add(
           "http://schemas.microsoft.com/office/word/2003/wordml",
           //to get this file I downloaded "Office 2003: XML Reference Schemas", i.e. "Office2003XMLSchema.exe" 
           @"C:\Program Files\Microsoft Office 2003 Developer Resources\Microsoft Office 2003 XML Reference Schemas\WordprocessingML Schemas\wordnet.xsd"
           );
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationEventHandler += new ValidationEventHandler(validationEventHandler);
        XmlReader xmlReader = XmlReader.Create(filename, settings);
        while (xmlReader.Read()) { }
   }

Моя проблема в том, что если я запускаю этот код на машине, которая не подключена к Интернету, я получаю ошибку XmlSchemaValidationException о том, что он не может найти xml.xsd.

Чтобы исправить это, я загрузил копию xml.xsd и явно добавил ее с помощью метода settings.Schemas.Add: проверка теперь работает правильно, когда машина не подключена к Интернету.

Однако, когда машина подключена к Интернету, теперь я получаю сообщение об ошибке, говорящее, что The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared..

Так что, по-видимому, мне либо нужно добавить его явно, либо нет, в зависимости от того, может ли машина автоматически загрузить его из Интернета (или даже, возможно, ранее могла загрузить его и где-то кэшировала).

Итак, «будь я проклят, если я сделаю это, и будь я проклят, если я этого не сделаю». Нужно ли мне попробовать это одним способом, поймать исключение, а затем попробовать другим способом? Или есть более элегантное решение?


person ChrisW    schedule 10.08.2010    source источник


Ответы (1)


Мы не видим ваш код, но Во многих реализациях это решается путем перенаправления запроса на .xsd в локальную копию с помощью преобразователя каталога. Существует свойство XmlReaderSettings.XmlResolver, которое можно использовать для этого. См. XMLCatalog.net для реализации с лицензией Apache, которую вы можете использовать.

Побочным эффектом этого является то, что вы можете хранить все схемы в локальном кэше. Это особенно важно, поскольку W3C будет блокировать избыточное чтение своего сайта, и случайным образом ваш код (или, что еще хуже, код вашего клиента) начнет давать сбой.

person lavinio    schedule 17.08.2010
comment
Спасибо за предложение; Я поэкспериментирую, чтобы увидеть, смогу ли я исправить это, используя подкласс System.Xml.XmlResolver. - person ChrisW; 19.08.2010
comment
У меня это работает сейчас. Раньше я терпел неудачу, потому что присваивал значение свойству XmlReaderSettings.XmlResolver; но когда/потому что я использую settings.Schemas.Add, мне нужно вместо этого назначить свойство settings.Schemas.XmlResolver. - person ChrisW; 19.08.2010
comment
@ChrisW: я также получаю сообщение об ошибке. Глобальный атрибут 'w3.org/XML/1998 /namespace:lang' уже объявлено с таким же кодом, как и в исходном вопросе. Вы установили settings.Schemas.XmlResolver в XMLCatalogResolver или что-то еще? Я попробовал это без везения. Есть ли шанс, что вы можете вставить свой рабочий код? - person Jeremy; 10.11.2011
comment
Привет, ChrisW, где ты нашел слово ML xsd? - person raman; 08.02.2021