Проблемы с разрешением DOCTYPE и ASP.Net - PullRequest
2 голосов
/ 01 апреля 2009

В предыдущем вопросе я упомянул некоторую работу со сторонней DLL, интерфейс которой использует серию входных XML-данных, которые определены с использованием DTD. Пока что все прошло гладко, но у меня все еще есть эта неприятная проблема с разрешением объявления типа документа в сгенерированных входных значениях.

Что я не могу понять, так это то, что решающим фактором является определение того, где искать ссылочный файл DTD. Если у меня есть объявление, которое выглядит так:

<!DOCTYPE ElementName SYSTEM "ElementName.dtd">

Сначала я думал, что текущий путь выполнения приложения - это место, где парсер будет искать DTD. Однако, когда я пытаюсь использовать XML-элемент управления в ASP.Net, полученная ошибка сбивает меня с толку ...

Не удалось найти файл 'c: \ Program Files \ Microsoft Visual студия 9,0 \ Common7 \ IDE \ ElementName.dtd '

Почему он ищет DTD там?

Есть ли какие-нибудь гуру XML, которые могут помочь мне в этом. Я действительно не имею никакого контроля над XML, который возвращается из этой DLL, так что я должен делать. Есть ли способ «зарегистрировать» DTD в операционной системе? Как GAC?

Ответы [ 2 ]

3 голосов
/ 01 апреля 2009

К сожалению, библиотека, сгенерировавшая XML, использовала относительный URL для dtd, а не полностью определенный. Таким образом, XmlDocument XmlControl использует класс XmlResolver для преобразования относительного пути в полностью определенный. По умолчанию используется XmlUrlResolver (это конкретный XmlResolver). Это попытается сопоставить местоположение dtd с местоположением, которое, по его мнению, относится к документу Xml. Проблема в том, где XmlDocument? Вероятно, в памяти, которая не относится ни к чему, и XmlUrlResolver использует вместо этого местоположение процесса, которое в вашем случае является Visual Studio, расположенным в «c: \ Program Files \ Microsoft Visual Studio 9.0 \ Common7 \ IDE \ devenv.exe».

Так что вы можете сделать? Ну, я полагаю, вы должны создать свой собственный XmlResolver, который наследует от XmlUrlResolver, переопределяет метод ResolveUri и делает что-то подходящее. Сделав это, вы должны будете:

  1. Создайте класс XmlReaderSettings и установите для свойства XmlReolver класс, который вы только что создали.
  2. Создайте XmlReader, используя XmlReader.Create (), передавая ваш документ и объект XmlSettings.
  3. Создайте XmlDocument и вызовите метод Load, передавая его в XmlReader и, наконец,
  4. Установите для свойства XmlDocument вашего XmlControl значение XmlDocument.

Честно говоря, все это немного болезненно, так что если бы это было так, я бы просто использовал string.Replace, чтобы удалить объявление DTD из документа перед его обработкой в ​​XML.

Если вы чувствуете себя действительно смелым, вы можете создать распознаватель, который наследуется непосредственно от XmlResolver. Сделав это, вы можете переопределить метод GetEntity , а затем вы можете получить документ dtd из любого места. Я однажды написал, что получил dtds из файлов, встроенных в файлы ресурсов, но, к сожалению, у меня больше нет кода: - (

0 голосов
/ 28 апреля 2009

Если вы на самом деле не заботитесь о проверке каждого документа по его DTD, вы можете установить для свойства XmlResolver значение null в XmlTextReader (или XmlDocument), чтобы полностью игнорировать DTD.

...