Класс System.Xml.XmlReader
В этой статье приводятся дополнительные замечания к справочной документации по этому 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 предоставляет конкретные реализации класса, такие как XmlTextReaderXmlNodeReader, и XmlValidatingReader классы, рекомендуется использовать специализированные классы XmlReader только в следующих сценариях:
- Если вы хотите считывать поддерев 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: структуры и часть 2 схемы W3C XML: рекомендации по типам данных.) Поэтому, хотя все допустимые XML-документы хорошо сформированы, не все хорошо сформированные XML-документы являются допустимыми.
Данные можно проверить на основе DTD, встроенной схемы XSD или схемы XSD, хранящейся в XmlSchemaSet объекте (кэше); эти сценарии описаны на эталонной Create странице. XmlReader не поддерживает проверку схемы XML-Data Reduced (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:noNamespaceSchemaLocation атрибутомxsi:schemaLocation . (Включено по умолчанию.)- ProcessInlineSchema - Обработка встроенных XML-схем во время проверки. (Отключено по умолчанию.)- ReportValidationWarnings --Отчет о событиях, если возникает предупреждение проверки. Предупреждение обычно формируется при отсутствии определения DTD или схемы XML для проверки конкретного элемента или атрибута. Параметр ValidationEventHandler используется для уведомления. (Отключено по умолчанию.) |
Schemas | XmlSchemaSet, используемый при проверке данных. |
Свойство XmlResolver | Разрешение XmlResolver и доступ к внешним ресурсам. Это может включать внешние сущности, такие как DTD и схемы, и любые xs:include или xs:import элементы, содержащиеся в схеме XML. Если вы не указываете, XmlResolverXmlReader использует значение по умолчанию 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-имена (например, имя элемента начинается с числа). |
Включено проверка символов и имен.false Параметр CheckCharacters отключения проверка символов для ссылок на сущности символов. Если средство чтения обрабатывает текстовые данные, всегда проверка допустимые имена 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, CommentWhitespaceи SignificantWhitespace. Узлы содержимого включают текст, отличный от пробелов, CDATAEntityReference иEndEntity. |
ReadSubtree | Считывает элемент и все его дочерние элементы и возвращает новый XmlReader набор ReadState.Initialэкземпляров. Этот метод полезен для создания границ вокруг XML-элементов; Например, если вы хотите передать данные другому компоненту для обработки, и вы хотите ограничить объем данных, к которым может получить доступ компонент. |
См. XmlReader.Read справочную страницу для примера перехода по текстовому потоку по одному узлу за раз и отображения типа каждого узла.
В следующих разделах описывается, как считывать определенные типы данных, такие как элементы, атрибуты и типизированные данные.
Чтение XML-элементов
В следующей таблице перечислены методы и свойства, предоставляемые классом XmlReader для обработки элементов. После того, как объект XmlReader позиционируется на элементе, свойства узла, например Name, отражают значения этого элемента. Кроме описанных ниже членов для обработки элементов процесса могут также использоваться любые методы и свойства класса XmlReader. Например, для чтения содержимого элемента используется метод ReadInnerXml.
Примечание.
См. раздел 3.1 рекомендации W3C XML 1.0 по определениям начальных тегов, конечных тегов и пустых тегов элементов.
Использование этого XmlReader элемента | По |
---|---|
IsStartElementМетод | Проверьте, является ли текущий узел тегом запуска или пустым тегом элемента. |
ReadStartElementМетод | Убедитесь, что текущий узел является элементом и перемещает средство чтения на следующий узел (вызовы IsStartElementRead, за которыми следует). |
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("<{0}/>", 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(" {0}", 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
В этом примере метод в цикле while
используется MoveToNextAttribute для перехода по атрибутам.
if (reader.HasAttributes) {
Console.WriteLine("Attributes of <" + reader.Name + ">");
while (reader.MoveToNextAttribute()) {
Console.WriteLine(" {0}={1}", 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 на узле Value объявления XML свойство возвращает версию, автономную и кодировку в виде одной строки. XmlReaderобъекты, созданные методомCreate, классом и XmlValidatingReader классом, предоставляют версию, XmlTextReader автономные и кодирующие элементы в виде атрибутов.
Чтение атрибутов на узлах типа документа
При расположении средства чтения 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: {0}", 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
.
Флаги ProcessInlineSchemaXmlReaderSettings проверки ProcessSchemaLocation объекта не задаются по умолчанию. Это позволяет защитить объект XmlReader от атак на основе схем при обработке XML-данных из ненадежного источника. Если эти флаги установлены, для разрешения расположения схем, обнаруженных в экземпляре документа в объекте XmlResolver, используется арбитр XmlReaderSettings объекта XmlReader. XmlResolver Если для свойства задано
null
значение, расположения схемы не разрешаются, даже если ProcessInlineSchema заданы флаги проверки.ProcessSchemaLocationСхемы, добавленные во время проверки, добавляют новые типы и могут изменить результат проверки документа. Поэтому следует разрешать только внешние схемы из доверенных источников.
Мы рекомендуем отключить ProcessIdentityConstraints флаг при проверке недоверенных, больших XML-документов в сценариях высокой доступности для схемы с ограничениями удостоверений в значительной части документа. Этот флаг включен по умолчанию.
XML-данные могут содержать большое количество атрибутов, деклараций пространств имен, вложенных элементов и так далее, на обработку которых требуется значительное время. Чтобы ограничить размер входных данных, отправляемых в нее XmlReader, можно:
Ограничить размер документа, задав MaxCharactersInDocument свойство.
Ограничить количество символов, которые приводят к расширению сущностей, задав MaxCharactersFromEntities свойство.
Создайте пользовательскую
IStream
реализацию для объекта XmlReader.
Этот ReadValueChunk метод можно использовать для обработки больших потоков данных. Этот метод за раз считывает небольшое число символов, а не выделяет одну строку для всего значения.
При чтении XML-документа с большим количеством уникальных локальных имен, пространств имен или префиксов может возникнуть проблема. Если вы используете класс, производный от XmlReader, и вызываете LocalNamePrefixсвойство , или NamespaceURI свойство для каждого элемента, возвращаемая строка добавляется в NameTable. Коллекция, удерживаемая NameTable никогда не уменьшается, создавая утечку виртуальной памяти дескрипторов строк. Одним из способов устранения этой проблемы является наследование класса NameTable и применение максимальной квоты размера. (Нет способа предотвратить использование NameTableили переключиться, NameTable когда оно заполнено). Другое решение заключается в том, чтобы избежать использования свойств, упоминание и вместо этого использовать MoveToAttribute метод с IsStartElement методом, где это возможно; эти методы не возвращают строки и таким образом избежать проблемы переполнения NameTable коллекции.
Объекты XmlReaderSettings могут содержать конфиденциальные сведения, например учетные данные пользователей. Ненадежный компонент может использовать объект XmlReaderSettings и его учетные данные пользователя, чтобы создавать объекты XmlReader для считывания данных. Будьте осторожны при кэшировании XmlReaderSettings объектов или при передаче XmlReaderSettings объекта из одного компонента в другой.
Не следует принимать вспомогательные компоненты, например объекты NameTable, XmlNamespaceManager и XmlResolver, из ненадежных источников.