




Используйте XMLReader для загрузки документа и установите для свойства ValidationType в настройках устройства чтения значение None.
Итак, у меня осталось ощущение, что необходимо обработать DTD, чтобы правильно обрабатывать ссылки на сущности. Но как это будет работать при отсутствии соединения?
Это не так. Если ваш документ может содержать ссылки на сущности, которые определены в DTD, синтаксическому анализатору потребуется DTD. Поэтому вам нужно либо включить DTD в XML, который вы пытаетесь проанализировать, либо кэшировать DTD локально. Это одна из причин, по которой мне не нравится использовать ссылки на сущности.
Попробуйте что-то вроде этого:
XmlDocument doc = new XmlDocument();
using (StringReader sr = new StringReader(xml))
using (XmlReader reader = XmlReader.Create(sr, new XmlReaderSettings()))
{
doc.Load(reader);
}
Здесь следует отметить, что в XmlReaderSettings для свойства ProhibitDtd по умолчанию установлено значение true.
Загружаемый документ ИМЕЕТ ОТД.
С:
settings.ProhibitDtd = true;
Я вижу следующее исключение:
Service cannot be started. System.Xml.XmlException: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the ProhibitDtd property on XmlReaderSettings to false and pass the settings into XmlReader.Create method.
Таким образом, похоже, что в этом случае для параметра ProhibitDtd ДОЛЖНО быть установлено значение true.
Похоже, ValidationType сработает, но с:
settings.ValidationType = ValidationType.None;
Я все еще вижу связь с URI DTD.
После некоторого рытья, возможно, вам следует установить для свойства XmlResolver объекта XmlReaderSettings значение null.
'The XmlResolver is used to locate and open an XML instance document, or to locate and open any external resources referenced by the XML instance document. This can include entities, DTD, or schemas.'
Итак, код будет выглядеть так:
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Parse;
XmlDocument doc = new XmlDocument();
using (StringReader sr = new StringReader(xml))
using (XmlReader reader = XmlReader.Create(sr, settings))
{
doc.Load(reader);
}
также требуется: settings.ProhibitDtd = false; в остальном прямо на деньгах. ваше здоровье!
Это полезный прием, но имейте в виду, что он не сработает для всех XML-документов. Если документ действительно каким-то образом ссылается на DTD (например, на ссылку на сущность), вы получите исключение XML, когда попытаетесь прочитать документ.
Я попробовал это и также обнаружил, что это работает, однако меня немного обеспокоил этот комментарий в документации MSDN: «Если установлено значение null, возникает исключение XmlException, когда XmlReader пытается получить доступ к внешнему ресурсу». Этого явно не происходит, но кто-нибудь знает почему? Кто-нибудь хочет это прокомментировать?
После некоторых экспериментов я обнаружил, что установка Обработки на Разбор все еще не позволяет получить DTD. Это помогло мне перестать казаться глупым: XmlReaderSettings settings = new XmlReaderSettings {DtdProcessing = DtdProcessing.Ignore};
На самом деле это недостаток спецификаций XML. W3C сетует на то, что все люди, как сумасшедшие, бьют по своим серверам, загружая схемы миллиарды раз. К сожалению, почти ни одна стандартная библиотека XML не понимает этого правильно, все они снова и снова попадают на серверы.
Проблема с DTD особенно серьезна, потому что DTD могут включать общие объявления сущностей (для таких вещей, как & -> &), на которые фактически может полагаться XML-файл. Так что, если ваш синтаксический анализатор предпочитает отказаться от загрузки DTD, а XML использует общие ссылки на сущности, синтаксический анализ может действительно потерпеть неудачу.
Единственным решением этой проблемы был бы прозрачный кэширующий преобразователь сущностей, который помещал бы загруженные файлы в некоторый архив в пути поиска библиотеки, так что этот архив будет динамически создаваться и почти автоматически объединяться с любыми созданными дистрибутивами программного обеспечения. Но даже в мире Java нет ни одного достойного такого EntityResolver, который бы не был встроен ни в что, начиная с Apache Foundation.
Это не поможет вам, если XML использует ссылки на сущности, определенные в DTD, к сожалению, потому что это делает XML некорректным, не недействительным.