Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
XmlReader предоставляет доступ только для чтения к XML-данным в документе или потоке. Этот класс соответствует рекомендациям W3C Extensible Markup Language (XML) 1.0 (четвертый выпуск) и пространства имен в XML 1.0 (третьем выпуске ).
XmlReader методы позволяют перемещаться по XML-данным и читать содержимое узла. Свойства класса отражают значение текущего узла, в котором расположен считыватель. Значение ReadState свойства указывает текущее состояние средства чтения XML. Например, свойство устанавливается ReadState.Initial методом XmlReader.Read и ReadState.Closed методом XmlReader.Close . XmlReader также обеспечивает проверки соответствия данным и проверку на соответствие DTD или схеме.
XmlReader использует модель извлечения для получения данных. Эта модель:
- Упрощает управление состоянием естественным образом, с помощью сверху вниз уточнения процедур.
- Поддерживает несколько входных потоков и слоев.
- Позволяет клиенту предоставить парсеру буфер, в который строка записывается напрямую, избегая необходимости дополнительного копирования строки.
- Поддерживает выборочную обработку. Клиент может пропускать элементы и обрабатывать те, которые представляют интерес для приложения. Вы также можете заранее задать свойства для управления процессом обработки XML-потока (например, нормализация).
Создание средства чтения XML
Используйте метод Create для создания экземпляра XmlReader.
Хотя .NET предоставляет конкретные реализации класса, такие как XmlReaderXmlTextReader, и XmlNodeReader классы, рекомендуется использовать специализированные классы XmlValidatingReader только в следующих сценариях:
- Если вы хотите считывать поддерев XML DOM из XmlNode объекта, используйте XmlNodeReader класс. (Однако этот класс не поддерживает проверку DTD или схемы.)
- Если необходимо развернуть сущности по запросу, вы не хотите нормализованное текстовое содержимое или не хотите возвращать атрибуты по умолчанию, используйте XmlTextReader класс.
Чтобы указать набор функций, которые необходимо включить в средстве чтения XML, передайте System.Xml.XmlReaderSettings объект в Create метод. Можно использовать один System.Xml.XmlReaderSettings объект для создания нескольких читателей с одной и той же функциональностью или изменения System.Xml.XmlReaderSettings объекта для создания нового средства чтения с другим набором функций. Вы также можете легко добавлять функции в существующее средство чтения.
Если вы не используете System.Xml.XmlReaderSettings объект, используются параметры по умолчанию. Дополнительные сведения см. на Create странице справки.
XmlReader выбрасывает XmlException при ошибках разбора XML. После возникновения исключения состояние средства чтения не предсказуемо. Например, тип сообщаемого узла может отличаться от фактического типа текущего узла. Используйте свойство ReadState, чтобы проверить, находится ли читатель в состоянии ошибки.
Проверка XML-данных
Чтобы определить структуру XML-документа и его связей элементов, типов данных и ограничений содержимого, используйте схему определения типа документа (DTD) или языка определения схемы XML (XSD). Xml-документ считается хорошо сформированным, если он соответствует всем синтаксическим требованиям, определенным рекомендацией W3C XML 1.0. Считается допустимым, если он хорошо сформирован, а также соответствует ограничениям, определенным его DTD или схемой. (См. Часть 1: Структуры W3C XML Schema и Часть 2: Типы данных W3C XML Schema.) Поэтому, хотя все допустимые XML-документы хорошо сформированы, не все хорошо сформированные XML-документы являются допустимыми.
Данные можно проверить на основе DTD, встроенной схемы XSD или схемы XSD, хранящейся в XmlSchemaSet объекте (кэше); эти сценарии описаны на эталонной Create странице. XmlReader не поддерживает проверку схемы XML-Data сокращенной (XDR).
Вы используете следующие настройки класса XmlReaderSettings, чтобы указать, какой тип проверки, если таковая имеется, поддерживает экземпляр XmlReader.
Использование этого XmlReaderSettings элемента | Указание |
---|---|
свойство DtdProcessing | Разрешать ли обработку DTD? Значение по умолчанию — запретить обработку DTD. |
свойство ValidationType | Следует ли читателю проверять данные и какой тип проверки выполнять (DTD или схема). По умолчанию проверка данных не выполняется. |
событие ValidationEventHandler | Обработчик событий для получения сведений о событиях проверки. Если обработчик событий не указан, XmlException будет выброшен при первой ошибке проверки. |
свойство ValidationFlags | Дополнительные опции проверки с помощью XmlSchemaValidationFlags элементов перечисления: - AllowXmlAttributes - Разрешить XML-атрибуты (xml:* ) в документах экземпляров, даже если они не определены в схеме. Атрибуты проверяются на основе их типа данных. См. справочную XmlSchemaValidationFlags страницу для параметра, используемого в определенных сценариях. (Отключено по умолчанию.)- ProcessIdentityConstraints --Обработка ограничений идентичности (xs:ID , xs:IDREF , xs:key , xs:keyref , xs:unique ), возникших во время проверки. (Включено по умолчанию.)- ProcessSchemaLocation --Process schemas, заданные атрибутом xsi:schemaLocation или атрибутом xsi:noNamespaceSchemaLocation . (Включено по умолчанию.)- ProcessInlineSchema - Обработка встроенных XML-схем во время проверки. (Отключено по умолчанию.)- ReportValidationWarnings --Отчет о событиях, если возникает предупреждение проверки. Предупреждение обычно выдается, если нет DTD или XML-схемы для проверки определенного элемента или атрибута. Используется ValidationEventHandler для уведомления. (Отключено по умолчанию.) |
Schemas | XmlSchemaSet используется для проверки. |
свойство XmlResolver | Средство XmlResolver для разрешения и доступа к внешним ресурсам. Это может включать внешние сущности, такие как DTD и схемы, и любые xs:include или xs:import элементы, содержащиеся в схеме XML. Если вы не указываете XmlResolver, то XmlReader использует XmlUrlResolver по умолчанию без учетных данных пользователя. |
Соответствие данным
Средства чтения XML, созданные методом Create , соответствуют следующим требованиям соответствия по умолчанию:
Новые строки и значение атрибута нормализуются в соответствии с рекомендацией W3C XML 1.0.
Все сущности автоматически развернуты.
Атрибуты по умолчанию, объявленные в определении типа документа, всегда добавляются, даже если средство чтения не проверяет.
Объявление префикса XML, сопоставленного с правильным URI пространства имен XML, разрешено.
Имена нотации в одном
NotationType
объявлении атрибута иNmTokens
в одномEnumeration
объявлении атрибута отличаются.
Используйте эти XmlReaderSettings свойства, чтобы указать тип проверок соответствия, которые требуется включить:
Используйте это XmlReaderSettings свойство | Кому | По умолчанию |
---|---|---|
свойство CheckCharacters | Включите или отключите проверки для следующих действий: — Символы находятся в диапазоне юридических XML-символов, как определено в разделе 2.2 Символов рекомендации W3C XML 1.0. — Все имена XML допустимы, как определено разделом 2.3 Common Syntactic Constructs в рекомендации W3C XML 1.0. Если для этого свойства задано значение true (по умолчанию), исключение возникает, XmlException если XML-файл содержит недопустимые символы или недопустимые XML-имена (например, имя элемента начинается с числа). |
Включена проверка символов и имен. Установка CheckCharacters в false отключает проверку символов для ссылок на символьные сущности. Если средство чтения обрабатывает текстовые данные, всегда проверяет допустимость имен XML независимо от этого параметра.
Заметка: Для рекомендации XML 1.0 требуется соответствие на уровне документа при наличии DTD. Поэтому, если средство чтения настроено для поддержки ConformanceLevel.Fragment, но XML-данные содержат определение типа документа (DTD), выбрасывается XmlException. |
свойство ConformanceLevel | Выберите уровень соответствия для принудительного применения: - Document. Соответствует правилам для хорошо сформированного документа XML 1.0. - Fragment. Соответствует правилам для хорошо сформированного фрагмента документа, который можно использовать в качестве внешней синтаксически разобранной сущности. - Auto. Соответствует уровню, определяемом читателем. Если данные не соответствуют требованиям, выбрасывается исключение XmlException. |
Document |
Навигация по узлам
Текущий узел — это узел XML, на котором в настоящее время размещается средство чтения XML. Все XmlReader методы выполняют операции в отношении этого узла, а все XmlReader свойства отражают значение текущего узла.
Следующие методы позволяют легко перемещаться по узлам и анализировать данные.
Используйте этот XmlReaderSettings метод | Кому |
---|---|
Read | Прочтите первый узел и проходите через поток, по одному узлу за раз. Такие вызовы обычно выполняются внутри while цикла.NodeType Используйте свойство, чтобы получить тип (например, атрибут, комментарий, элемент и т. д.) текущего узла. |
Skip | Пропустите дочерние элементы текущего узла и перейдите к следующему узлу. |
MoveToContent и MoveToContentAsync. | Пропустите узлы, отличные от содержимого, и перейдите к следующему узлу содержимого или к концу файла. Узлы, отличные от содержимого, включают ProcessingInstruction, DocumentType, Comment, Whitespace и SignificantWhitespace. Узлы содержимого включают текст, не являющийся пробелом, CDATA, EntityReference и EndEntity. |
ReadSubtree | Считывает элемент и все его дочерние элементы и возвращает новый XmlReader экземпляр, установленный на ReadState.Initial. Этот метод полезен для создания границ вокруг XML-элементов; Например, если вы хотите передать данные другому компоненту для обработки, и вы хотите ограничить объем данных, к которым может получить доступ компонент. |
См. XmlReader.Read справочную страницу для примера перехода по текстовому потоку по одному узлу за раз и отображения типа каждого узла.
В следующих разделах описывается, как считывать определенные типы данных, такие как элементы, атрибуты и типизированные данные.
Чтение XML-элементов
В следующей таблице перечислены методы и свойства, предоставляемые классом XmlReader для обработки элементов. После размещения XmlReader на элементе свойства узла, например, Name, отражают значения элементов. Помимо элементов, описанных ниже, можно также использовать любые общие методы и свойства XmlReader класса для обработки элементов. Например, можно использовать ReadInnerXml метод для чтения содержимого элемента.
Примечание.
См. раздел 3.1 рекомендации W3C XML 1.0 по определениям начальных тегов, конечных тегов и пустых тегов элементов.
Использование этого XmlReader элемента | Кому |
---|---|
IsStartElementМетод | Проверьте, является ли текущий узел тегом запуска или пустым тегом элемента. |
ReadStartElementМетод | Убедитесь, что текущий узел является элементом, и переместите средство чтения на следующий узел (вызываются IsStartElement, за которым следует Read). |
ReadEndElementМетод | Убедитесь, что текущий узел является конечным тегом, и перейдите к следующему узлу. |
ReadElementStringМетод | Читать текстовый элемент. |
ReadToDescendantМетод | Переведите средство чтения XML на следующий дочерний элемент, имеющий указанное имя. |
ReadToNextSiblingМетод | Переведите средство чтения XML на следующий элемент с общим значением, который имеет указанное имя. |
свойство IsEmptyElement | Проверьте, имеет ли текущий элемент тег конечного элемента. Рассмотрим пример. - <item num="123"/> (IsEmptyElement имеет true значение .)- <item num="123"> </item> ( имеетIsEmptyElementfalse значение , хотя содержимое элемента пусто.) |
Пример чтения текстового содержимого элементов см. в методе ReadString . В следующем примере элементы обрабатываются с помощью while
цикла.
while (reader.Read()) {
if (reader.IsStartElement()) {
if (reader.IsEmptyElement)
{
Console.WriteLine($"<{reader.Name}/>");
}
else {
Console.Write("<{0}> ", reader.Name);
reader.Read(); // Read the start tag.
if (reader.IsStartElement()) // Handle nested elements.
Console.Write("\r\n<{0}>", reader.Name);
Console.WriteLine(reader.ReadString()); //Read the text content of the element.
}
}
}
While reader.Read()
If reader.IsStartElement() Then
If reader.IsEmptyElement Then
Console.WriteLine("<{0}/>", reader.Name)
Else
Console.Write("<{0}> ", reader.Name)
reader.Read() ' Read the start tag.
If reader.IsStartElement() Then ' Handle nested elements.
Console.Write(vbCr + vbLf + "<{0}>", reader.Name)
End If
Console.WriteLine(reader.ReadString()) 'Read the text content of the element.
End If
End If
End While
Чтение XML-атрибутов
Атрибуты XML чаще всего находятся в элементах, но они также разрешены в объявлениях XML и узлах типов документов.
При нахождении на узле элемента метод MoveToAttribute позволяет вам просматривать список атрибутов элемента. Обратите внимание, что после MoveToAttribute вызова свойства узла, такие как Name, NamespaceURIи Prefix отражают свойства этого атрибута, а не свойства элемента, к которому принадлежит атрибут.
Класс XmlReader предоставляет эти методы и свойства для чтения и обработки атрибутов элементов.
Использование этого XmlReader элемента | Кому |
---|---|
свойство HasAttributes | Проверьте, имеет ли текущий узел какие-либо атрибуты. |
свойство AttributeCount | Получите количество атрибутов текущего элемента. |
MoveToFirstAttributeМетод | Перейдите к первому атрибуту в элементе. |
MoveToNextAttributeМетод | Перейдите к следующему атрибуту в элементе. |
MoveToAttributeМетод | Перейдите к указанному атрибуту. |
GetAttribute метод или Item[] свойство | Получите значение указанного атрибута. |
свойство IsDefault | Проверьте, является ли текущий узел атрибутом, созданным из значения по умолчанию, определенного в DTD или схеме. |
MoveToElementМетод | Перейдите к элементу, которому принадлежит текущий атрибут. Используйте этот метод, чтобы вернуться к элементу после перехода по его атрибутам. |
ReadAttributeValueМетод | Выполните разбор значения атрибута на один или несколько узлов Text , EntityReference или EndEntity . |
Для обработки атрибутов также можно использовать любой из общих XmlReader методов и свойств. Например, после того как XmlReader расположен на атрибуте, свойства Name и Value отражают значения атрибута. Для получения значения атрибута можно также использовать любой из методов содержимого Read
.
В этом примере используется свойство AttributeCount для перехода ко всем атрибутам элемента.
// Display all attributes.
if (reader.HasAttributes) {
Console.WriteLine("Attributes of <" + reader.Name + ">");
for (int i = 0; i < reader.AttributeCount; i++) {
Console.WriteLine($" {reader[i]}");
}
// Move the reader back to the element node.
reader.MoveToElement();
}
' Display all attributes.
If reader.HasAttributes Then
Console.WriteLine("Attributes of <" + reader.Name + ">")
Dim i As Integer
For i = 0 To (reader.AttributeCount - 1)
Console.WriteLine(" {0}", reader(i))
Next i
' Move the reader back to the element node.
reader.MoveToElement()
End If
В этом примере метод MoveToNextAttribute используется в цикле while
для перехода по атрибутам.
if (reader.HasAttributes) {
Console.WriteLine("Attributes of <" + reader.Name + ">");
while (reader.MoveToNextAttribute()) {
Console.WriteLine($" {reader.Name}={reader.Value}");
}
// Move the reader back to the element node.
reader.MoveToElement();
}
If reader.HasAttributes Then
Console.WriteLine("Attributes of <" + reader.Name + ">")
While reader.MoveToNextAttribute()
Console.WriteLine(" {0}={1}", reader.Name, reader.Value)
End While
' Move the reader back to the element node.
reader.MoveToElement()
End If
Чтение атрибутов в узлах декларации XML
При расположении средства чтения XML на узле объявления XML свойство возвращает информацию о версии, самодостаточности и кодировке в виде одной строки. XmlReader объекты, созданные методом Create, классом XmlTextReader и классом XmlValidatingReader, предоставляют версию, standalone и encoding как атрибуты.
Чтение атрибутов с узлов типа документа
При нахождении XML-ридера на узле типа документа можно использовать метод GetAttribute и свойство Item[], чтобы вернуть значения для литералов SYSTEM и PUBLIC. Например, вызов reader.GetAttribute("PUBLIC")
возвращает значение PUBLIC.
Чтение атрибутов на узлах инструкций обработки
Когда XmlReader располагается на узле инструкций обработки, свойство Value возвращает всё текстовое содержимое. Элементы в узле инструкций обработки не рассматриваются как атрибуты. Их нельзя читать с помощью метода GetAttribute или метода MoveToAttribute.
Чтение XML-содержимого
Класс XmlReader содержит следующие элементы, которые считывают содержимое из XML-файла и возвращают содержимое в виде строковых значений. (Чтобы вернуть типы CLR, см. "Преобразование в типы CLR".)
Использование этого XmlReader элемента | Кому |
---|---|
свойство Value | Получите текстовое содержимое текущего узла. Возвращаемое значение зависит от типа узла; Дополнительные сведения см. на Value странице справки. |
ReadStringМетод | Получение содержимого элемента или текстового узла в виде строки. Этот метод останавливает обработку инструкций и комментариев. Дополнительные сведения о том, как этот метод обрабатывает определенные типы узлов, см. на справочной ReadString странице. |
методы ReadInnerXml и ReadInnerXmlAsync | Получите все содержимое текущего узла, включая разметку, но исключая начальные и конечные теги. Например, для:<node>this<child id="123"/></node> ReadInnerXml возвращает: this<child id="123"/> |
методы ReadOuterXml и ReadOuterXmlAsync | Получите все содержимое текущего узла и его дочерних объектов, включая разметку и теги начала и окончания. Например, для:<node>this<child id="123"/></node> ReadOuterXml возвращает: <node>this<child id="123"/></node> |
Преобразование в типы CLR
Элементы класса (перечисленные в следующей XmlReader таблице) можно использовать для чтения XML-данных и возвращаемых значений в виде типов среды CLR вместо строк. Эти члены позволяют получать значения в представлении, которое наиболее подходит для задачи программирования, не выполняя ручной анализ или преобразование строковых значений.
Методы ReadElementContentAs могут вызываться только в типах узлов элементов. Эти методы нельзя использовать для элементов, содержащих дочерние элементы или смешанное содержимое. При вызове XmlReader объект считывает начальный тег, считывает содержимое элемента, а затем перемещается мимо тега конечного элемента. Инструкции по обработке и комментарии игнорируются, а сущности расширяются.
Методы ReadContentAs считывают текстовое содержимое на текущей позиция чтения, и если для XML-данных отсутствует информация о схеме или типе данных, преобразуют текстовое содержимое в запрошенный тип возвращаемого значения. Текст, пробелы, значительные пробелы и разделы CDATA объединяются. Комментарии и инструкции по обработке пропускаются, а ссылки на сущности разрешаются автоматически.
Класс XmlReader использует правила, определенные рекомендацией по схеме XML W3C 2.
Используйте этот XmlReader метод | чтобы вернуть этот тип CLR |
---|---|
ReadContentAsBoolean и ReadElementContentAsBoolean. | Boolean |
ReadContentAsDateTime и ReadElementContentAsDateTime. | DateTime |
ReadContentAsDouble и ReadElementContentAsDouble. | Double |
ReadContentAsLong и ReadElementContentAsLong. | Int64 |
ReadContentAsInt и ReadElementContentAsInt. | Int32 |
ReadContentAsString и ReadElementContentAsString. | String |
ReadContentAs и ReadElementContentAs. | Тип, который вы указываете с помощью параметра returnType |
ReadContentAsObject и ReadElementContentAsObject. | Наиболее подходящий тип, указанный свойством XmlReader.ValueType . Сведения о сопоставлении см. в разделе "Поддержка типов в классах System.Xml". |
Если элемент не может быть легко преобразован в тип CLR из-за формата, можно использовать сопоставление со схемой, чтобы обеспечить успешное преобразование. В следующем примере используется .xsd файл для преобразования элемента hire-date
в тип xs:date
, а затем используется метод ReadElementContentAsDateTime для возврата элемента в виде объекта DateTime.
Входные данные (hireDate.xml):
<employee xmlns="urn:empl-hire">
<ID>12365</ID>
<hire-date>2003-01-08</hire-date>
<title>Accountant</title>
</employee>
Схема (hireDate.xsd):
<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="urn:empl-hire" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="employee">
<xs:complexType>
<xs:sequence>
<xs:element name="ID" type="xs:unsignedShort" />
<xs:element name="hire-date" type="xs:date" />
<xs:element name="title" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Код:
// Create a validating XmlReader object. The schema
// provides the necessary type information.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add("urn:empl-hire", "hireDate.xsd");
using (XmlReader reader = XmlReader.Create("hireDate.xml", settings)) {
// Move to the hire-date element.
reader.MoveToContent();
reader.ReadToDescendant("hire-date");
// Return the hire-date as a DateTime object.
DateTime hireDate = reader.ReadElementContentAsDateTime();
Console.WriteLine($"Six Month Review Date: {hireDate.AddMonths(6)}");
}
' Create a validating XmlReader object. The schema
' provides the necessary type information.
Dim settings As XmlReaderSettings = New XmlReaderSettings()
settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("urn:empl-hire", "hireDate.xsd")
Using reader As XmlReader = XmlReader.Create("hireDate.xml", settings)
' Move to the hire-date element.
reader.MoveToContent()
reader.ReadToDescendant("hire-date")
' Return the hire-date as a DateTime object.
Dim hireDate As DateTime = reader.ReadElementContentAsDateTime()
Console.WriteLine("Six Month Review Date: {0}", hireDate.AddMonths(6))
End Using
Выходные данные:
Six Month Review Date: 7/8/2003 12:00:00 AM
Асинхронное программирование
XmlReader Большинство методов имеют асинхронные аналоги, имеющие Async в конце их имен методов. Например, асинхронный эквивалент ReadContentAsObject равен ReadContentAsObjectAsync.
Следующие методы можно использовать с асинхронными вызовами методов:
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
В следующих разделах описано асинхронное использование методов, которые не имеют асинхронных аналогов.
Метод ReadStartElement
public static async Task ReadStartElementAsync(this XmlReader reader, string localname, string ns)
{
if (await reader.MoveToContentAsync() != XmlNodeType.Element)
{
throw new InvalidOperationException(reader.NodeType.ToString() + " is an invalid XmlNodeType");
}
if ((reader.LocalName == localname) && (reader.NamespaceURI == ns))
{
await reader.ReadAsync();
}
else
{
throw new InvalidOperationException("localName or namespace doesn’t match");
}
}
<Extension()>
Public Async Function ReadStartElementAsync(reader As XmlReader, localname As String, ns As String) As Task
If (Await reader.MoveToContentAsync() <> XmlNodeType.Element) Then
Throw New InvalidOperationException(reader.NodeType.ToString() + " is an invalid XmlNodeType")
End If
If ((reader.LocalName = localname) And (reader.NamespaceURI = ns)) Then
Await reader.ReadAsync()
Else
Throw New InvalidOperationException("localName or namespace doesn’t match")
End If
End Function
Метод ReadEndElement
public static async Task ReadEndElementAsync(this XmlReader reader)
{
if (await reader.MoveToContentAsync() != XmlNodeType.EndElement)
{
throw new InvalidOperationException();
}
await reader.ReadAsync();
}
<Extension()>
Public Async Function ReadEndElementAsync(reader As XmlReader) As task
If (Await reader.MoveToContentAsync() <> XmlNodeType.EndElement) Then
Throw New InvalidOperationException()
End If
Await reader.ReadAsync()
End Function
Метод ReadToNextSibling
public static async Task<bool> ReadToNextSiblingAsync(this XmlReader reader, string localName, string namespaceURI)
{
if (localName == null || localName.Length == 0)
{
throw new ArgumentException("localName is empty or null");
}
if (namespaceURI == null)
{
throw new ArgumentNullException("namespaceURI");
}
// atomize local name and namespace
localName = reader.NameTable.Add(localName);
namespaceURI = reader.NameTable.Add(namespaceURI);
// find the next sibling
XmlNodeType nt;
do
{
await reader.SkipAsync();
if (reader.ReadState != ReadState.Interactive)
break;
nt = reader.NodeType;
if (nt == XmlNodeType.Element &&
((object)localName == (object)reader.LocalName) &&
((object)namespaceURI ==(object)reader.NamespaceURI))
{
return true;
}
} while (nt != XmlNodeType.EndElement && !reader.EOF);
return false;
}
<Extension()>
Public Async Function ReadToNextSiblingAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
If (localName = Nothing Or localName.Length = 0) Then
Throw New ArgumentException("localName is empty or null")
End If
If (namespaceURI = Nothing) Then
Throw New ArgumentNullException("namespaceURI")
End If
' atomize local name and namespace
localName = reader.NameTable.Add(localName)
namespaceURI = reader.NameTable.Add(namespaceURI)
' find the next sibling
Dim nt As XmlNodeType
Do
Await reader.SkipAsync()
If (reader.ReadState <> ReadState.Interactive) Then
Exit Do
End If
nt = reader.NodeType
If ((nt = XmlNodeType.Element) And
((CObj(localName) = CObj(reader.LocalName))) And
(CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
Return True
End If
Loop While (nt <> XmlNodeType.EndElement And (Not reader.EOF))
Return False
End Function
Метод ReadToFollowing
public static async Task<bool> ReadToFollowingAsync(this XmlReader reader, string localName, string namespaceURI)
{
if (localName == null || localName.Length == 0)
{
throw new ArgumentException("localName is empty or null");
}
if (namespaceURI == null)
{
throw new ArgumentNullException("namespaceURI");
}
// atomize local name and namespace
localName = reader.NameTable.Add(localName);
namespaceURI = reader.NameTable.Add(namespaceURI);
// find element with that name
while (await reader.ReadAsync())
{
if (reader.NodeType == XmlNodeType.Element && ((object)localName == (object)reader.LocalName) && ((object)namespaceURI == (object)reader.NamespaceURI))
{
return true;
}
}
return false;
}
<Extension()>
Public Async Function ReadToFollowingAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
If (localName = Nothing Or localName.Length = 0) Then
Throw New ArgumentException("localName is empty or null")
End If
If (namespaceURI = Nothing) Then
Throw New ArgumentNullException("namespaceURI")
End If
' atomize local name and namespace
localName = reader.NameTable.Add(localName)
namespaceURI = reader.NameTable.Add(namespaceURI)
' find element with that name
While (Await reader.ReadAsync())
If ((reader.NodeType = XmlNodeType.Element) And
(CObj(localName) = CObj(reader.LocalName)) And
(CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
Return True
End If
End While
Return False
End Function
Метод ReadToDescendant
public static async Task<bool> ReadToDescendantAsync(this XmlReader reader, string localName, string namespaceURI)
{
if (localName == null || localName.Length == 0)
{
throw new ArgumentException("localName is empty or null");
}
if (namespaceURI == null)
{
throw new ArgumentNullException("namespaceURI");
}
// save the element or root depth
int parentDepth = reader.Depth;
if (reader.NodeType != XmlNodeType.Element)
{
// adjust the depth if we are on root node
if (reader.ReadState == ReadState.Initial)
{
parentDepth--;
}
else
{
return false;
}
}
else if (reader.IsEmptyElement)
{
return false;
}
// atomize local name and namespace
localName = reader.NameTable.Add(localName);
namespaceURI = reader.NameTable.Add(namespaceURI);
// find the descendant
while (await reader.ReadAsync() && reader.Depth > parentDepth)
{
if (reader.NodeType == XmlNodeType.Element && ((object)localName == (object)reader.LocalName) && ((object)namespaceURI == (object)reader.NamespaceURI))
{
return true;
}
}
return false;
}
<Extension()>
Public Async Function ReadToDescendantAsync(reader As XmlReader, localName As String, namespaceURI As String) As Task(Of Boolean)
If (localName = Nothing Or localName.Length = 0) Then
Throw New ArgumentException("localName is empty or null")
End If
If (namespaceURI = Nothing) Then
Throw New ArgumentNullException("namespaceURI")
End If
' save the element or root depth
Dim parentDepth As Integer = reader.Depth
If (reader.NodeType <> XmlNodeType.Element) Then
' adjust the depth if we are on root node
If (reader.ReadState = ReadState.Initial) Then
parentDepth -= 1
Else
Return False
End If
ElseIf (reader.IsEmptyElement) Then
Return False
End If
' atomize local name and namespace
localName = reader.NameTable.Add(localName)
namespaceURI = reader.NameTable.Add(namespaceURI)
' find the descendant
While (Await reader.ReadAsync() And reader.Depth > parentDepth)
If (reader.NodeType = XmlNodeType.Element And
(CObj(localName) = CObj(reader.LocalName)) And
(CObj(namespaceURI) = CObj(reader.NamespaceURI))) Then
Return True
End If
End While
Return False
End Function
Вопросы безопасности
При работе с классом XmlReader учтите следующее:
Исключения, вызываемые из XmlReader, могут раскрыть сведения о пути, которые вы, возможно, не хотите, чтобы они доходили до вашего приложения. Приложение должно перехватывать исключения и обрабатывать их соответствующим образом.
Не включите обработку DTD, если вас беспокоит проблема с отказом в обслуживании или если вы работаете с ненадежными источниками. Обработка DTD отключена по умолчанию для XmlReader объектов, созданных методом Create .
Если у вас включена обработка DTD, можно использовать XmlSecureResolver для ограничения ресурсов, к которым XmlReader можно получить доступ. Вы также можете разработать приложение, чтобы обработка XML была ограниченной памятью и временем. Например, можно настроить ограничения времени ожидания в приложении ASP.NET.
XML-данные могут содержать ссылки на внешние ресурсы, такие как файл схемы. По умолчанию внешние ресурсы разрешаются с помощью объекта XmlUrlResolver без учетных данных пользователя. Вы можете защитить это дальше, выполнив одно из следующих действий:
Ограничьте ресурсы, к которым XmlReader может получить доступ, установив для свойства XmlReaderSettings.XmlResolver объект XmlSecureResolver.
Не разрешайте XmlReader открывать внешние ресурсы, установив значение XmlReaderSettings.XmlResolver для свойства
null
.
Флаги проверки ProcessInlineSchema и ProcessSchemaLocation объекта XmlReaderSettings не задаются по умолчанию. Это помогает защитить XmlReader от атак на основе схем при обработке XML-данных из ненадежного источника. Если эти флаги заданы, XmlResolver объекта XmlReaderSettings используется для разрешения расположений схем, встречающихся в документе экземпляра XmlReader. Если для свойства XmlResolver установлено значение
null
, расположения схемы не разрешаются, даже если установлены флаги проверки ProcessInlineSchema и ProcessSchemaLocation.Схемы, добавленные во время проверки, добавляют новые типы и могут изменить результаты проверки проверяемого документа. Следовательно, внешние схемы должны браться на рассмотрение только из надежных источников.
Мы рекомендуем отключить флаг ProcessIdentityConstraints при валидации ненадежных, больших XML-документов в сценариях высокой доступности на основе схемы с ограничениями идентичности для значительной части документа. Этот флаг включен по умолчанию.
XML-данные могут содержать большое количество атрибутов, объявлений пространства имен, вложенных элементов и т. д., для которых требуется значительное время для обработки. Чтобы ограничить размер входных данных, отправляемых в нее XmlReader, можно:
Ограничить размер документа, задав MaxCharactersInDocument свойство.
Ограничьте количество символов, получающихся при расширении сущностей, задав свойство MaxCharactersFromEntities.
Создайте пользовательскую
IStream
реализацию для XmlReader.
Этот ReadValueChunk метод можно использовать для обработки больших потоков данных. Этот метод считывает небольшое количество символов за раз вместо выделения одной строки для всего значения.
При чтении XML-документа с большим количеством уникальных локальных имен, пространств имен или префиксов может возникнуть проблема. Если вы используете класс, производный от XmlReader, и вызываете свойство LocalName, Prefix или NamespaceURI для каждого элемента, возвращаемая строка добавляется в NameTable. Коллекция, удерживаемая NameTable, никогда не уменьшается в размерах, создавая виртуальную утечку ресурсов памяти дескрипторов строк. Одним из способов устранения этой проблемы является наследование класса NameTable и применение максимальной квоты размера. (Нет способа предотвратить использование NameTable или переключить NameTable на что-то другое, когда оно заполнено). Ещё один способ снижения риска заключается в том, чтобы избегать использования упомянутых свойств и вместо этого использовать метод MoveToAttribute вместе с методом IsStartElement, где это возможно; эти методы не возвращают строки, и таким образом проблема перезаполнения коллекции NameTable не возникает.
XmlReaderSettings объекты могут содержать конфиденциальную информацию, например учетные данные пользователя. Ненадежный компонент может использовать XmlReaderSettings объект и учетные данные пользователя для создания XmlReader объектов для чтения данных. Будьте осторожны при кэшировании XmlReaderSettings объектов или при передаче XmlReaderSettings объекта из одного компонента в другой.
Не принимать вспомогательные компоненты, такие как NameTable, XmlNamespaceManagerи XmlResolver объекты, из ненадежного источника.