Использование .NET для проверки XML по схеме - PullRequest
10 голосов
/ 10 августа 2010

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

По сути, это схема WordML Word 2003, которую 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..

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

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

1 Ответ

4 голосов
/ 17 августа 2010

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

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

...