Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Observação
Este artigo fornece observações complementares à documentação de referência para esta API.
XmlReader fornece acesso somente encaminhamento e somente leitura a dados XML em um documento ou fluxo. Esta classe está em conformidade com as recomendações do W3C Extensible Markup Language (XML) 1.0 (quarta edição) e do Namespaces em XML 1.0 (terceira edição).
XmlReader métodos permitem que você se mova através de dados XML e leia o conteúdo de um nó. As propriedades da classe refletem o valor do nó atual, que é onde o leitor está posicionado. O valor da propriedade ReadState indica o estado atual do leitor XML. Por exemplo, a propriedade é definida como ReadState.Initial pelo método XmlReader.Read e ReadState.Closed pelo método XmlReader.Close. XmlReader também fornece verificações de conformidade de dados e validação em relação a um DTD ou esquema.
XmlReader usa um modelo pull para recuperar dados. Este modelo:
- Simplifica a gestão do estado através de um refinamento processual natural de cima para baixo.
- Suporta vários fluxos de entrada e camadas.
- Permite que o cliente dê ao analisador um buffer no qual a cadeia de caracteres é gravada diretamente e, assim, evita a necessidade de uma cópia de cadeia de caracteres extra.
- Suporta processamento seletivo. O cliente pode ignorar itens e processar aqueles que são de interesse para o aplicativo. Você também pode definir propriedades com antecedência para gerenciar como o fluxo XML é processado (por exemplo, normalização).
Criar um leitor XML
Use o método Create para criar uma instância XmlReader.
Embora o .NET forneça implementações concretas da classe XmlReader, como as classes XmlTextReader, XmlNodeReadere XmlValidatingReader, recomendamos que você use as classes especializadas somente nestes cenários:
- Quando você quiser ler uma subárvore DOM XML de um objeto XmlNode, use a classe XmlNodeReader. (No entanto, essa classe não oferece suporte a DTD ou validação de esquema.)
- Se você precisar expandir entidades mediante solicitação, não quiser que seu conteúdo de texto seja normalizado ou não quiser que os atributos padrão retornem, use a classe XmlTextReader.
Para especificar o conjunto de recursos que você deseja habilitar no leitor XML, passe um objeto System.Xml.XmlReaderSettings para o método Create. Você pode usar um único objeto System.Xml.XmlReaderSettings para criar vários leitores com a mesma funcionalidade ou modificar o objeto System.Xml.XmlReaderSettings para criar um novo leitor com um conjunto diferente de recursos. Você também pode facilmente adicionar recursos a um leitor existente.
Se você não usar um objeto System.Xml.XmlReaderSettings, as configurações padrão serão usadas. Consulte a página de referência Create para obter detalhes.
XmlReader lança um XmlException em erros de parsing XML. Após uma exceção ser lançada, o estado do leitor não pode ser previsto. Por exemplo, o tipo de nó informado pode ser diferente do tipo de nó real do nó atual. Use a propriedade ReadState para verificar se o leitor está em estado de erro.
Validar dados XML
Para definir a estrutura de um documento XML e suas relações de elementos, tipos de dados e restrições de conteúdo, use um esquema DTD (definição de tipo de documento) ou XSD (linguagem de definição de esquema XML). Um documento XML é considerado bem formado se atender a todos os requisitos sintáticos definidos pelo de Recomendação XML 1.0 doW3C. É considerado válido se estiver bem formado e também estiver em conformidade com as restrições definidas pelo seu DTD ou esquema. (Consulte o W3C XML Schema Part 1: Structures e o W3C XML Schema Part 2: Datatypes recommendations.) Portanto, embora todos os documentos XML válidos estejam bem formados, nem todos os documentos XML bem formados são válidos.
Você pode validar os dados em relação a um DTD, um esquema XSD embutido ou um esquema XSD armazenado em um objeto XmlSchemaSet (um cache); Esses cenários são descritos na página de referência Create. XmlReader não suporta a validação de esquema XDR reduzido pelo XML-Data.
Use as seguintes configurações na classe XmlReaderSettings para especificar que tipo de validação, se houver, a instância XmlReader suporta.
| Use este membro XmlReaderSettings | Para especificar |
|---|---|
| DtdProcessing propriedade | Se o processamento DTD deve ser permitido. O padrão é não permitir o processamento DTD. |
| ValidationType propriedade | Se o leitor deve validar dados e que tipo de validação executar (DTD ou esquema). O padrão é nenhuma validação de dados. |
| evento ValidationEventHandler | Um manipulador de eventos para receber informações sobre eventos de validação. Se um manipulador de eventos não for fornecido, um XmlException será lançado no primeiro erro de validação. |
| ValidationFlags propriedade | Opções de validação adicionais através dos membros da enumeração XmlSchemaValidationFlags: - AllowXmlAttributes-- Permite atributos XML (xml:*) em documentos de instância, mesmo quando eles não estão definidos no esquema. Os atributos são validados com base em seu tipo de dados. Consulte a página de referência XmlSchemaValidationFlags para obter a configuração a ser usada em cenários específicos. (Desativado por padrão.)- ProcessIdentityConstraints --Processar restrições de identidade (xs:ID, xs:IDREF, xs:key, xs:keyref, xs:unique) encontradas durante a validação. (Ativado por padrão.)- ProcessSchemaLocation --Esquemas de processo especificados pelo atributo xsi:schemaLocation ou xsi:noNamespaceSchemaLocation. (Ativado por padrão.)- ProcessInlineSchema-- Processe esquemas XML embutidos durante a validação. (Desativado por padrão.)- ReportValidationWarnings--Relatar eventos se ocorrer um aviso de validação. Um aviso geralmente é emitido quando não há DTD ou esquema XML para validar um determinado elemento ou atributo. O ValidationEventHandler é usado para notificação. (Desativado por padrão.) |
| Schemas | O XmlSchemaSet a ser usado para validação. |
| XmlResolver propriedade | O XmlResolver para resolver e acessar recursos externos. Isso pode incluir entidades externas, como DTD e esquemas, e quaisquer elementos xs:include ou xs:import contidos no esquema XML. Se você não especificar um XmlResolver, o XmlReader usará um XmlUrlResolver padrão sem credenciais de usuário. |
Conformidade dos dados
Os leitores XML criados pelo método Create atendem aos seguintes requisitos de conformidade por padrão:
Novas linhas e valor de atributo são normalizados de acordo com a Recomendação W3C XML 1.0.
Todas as entidades são expandidas automaticamente.
Os atributos padrão declarados na definição de tipo de documento são sempre adicionados, mesmo quando o leitor não valida.
É permitida a declaração do prefixo XML mapeado para o URI do namespace XML correto.
Os nomes de notação em uma única declaração de atributo
NotationTypeeNmTokensem uma única declaração de atributoEnumerationsão distintos.
Use estas propriedades XmlReaderSettings para especificar o tipo de verificações de conformidade que você deseja habilitar:
| Use esta propriedade XmlReaderSettings | Para | Predefinido |
|---|---|---|
| CheckCharacters propriedade | Habilite ou desabilite as verificações para o seguinte: - Os caracteres estão dentro do intervalo de caracteres XML legais, conforme definido pela seção 2.2 Caracteres da Recomendação XML 1.0 do W3C. - Todos os nomes XML são válidos, conforme definido pela seção 2.3 Common Syntactic Constructs da Recomendação W3C XML 1.0. Quando essa propriedade é definida como true (padrão), uma exceção de XmlException é lançada se o arquivo XML contiver caracteres ilegais ou nomes XML inválidos (por exemplo, um nome de elemento começa com um número). |
A verificação de caracteres e nomes está ativada. Ao definir CheckCharacters para false, desliga-se a verificação de entidades de referência de caracteres. Se o leitor estiver processando dados de texto, ele sempre verificará se os nomes XML são válidos, independentemente dessa configuração.
Nota: A recomendação XML 1.0 requer conformidade no nível do documento quando um DTD está presente. Portanto, se o leitor estiver configurado para suportar ConformanceLevel.Fragment, mas os dados XML contiverem uma definição de tipo de documento (DTD), uma XmlException será lançada. |
| ConformanceLevel propriedade | Escolha o nível de conformidade a aplicar: - Document. Está em conformidade com as regras para um documento XML 1.0 bem formado . - Fragment. Está em conformidade com as regras para um fragmento de documento bem formado que pode ser consumido como uma entidade analisada externa . - Auto. Está em conformidade com o nível decidido pelo leitor. Se os dados não estiverem em conformidade, uma exceção XmlException será lançada. |
Document |
Navegar pelos nós
O nó XML em que o leitor XML está posicionado atualmente é o nó atual. Todos os métodos XmlReader executam operações em relação a esse nó e todas as propriedades XmlReader refletem o valor do nó atual.
Os métodos a seguir facilitam a navegação pelos nós e a análise de dados.
| Use este método XmlReaderSettings | Para |
|---|---|
| Read | Leia o primeiro nó e avance pelo fluxo um nó de cada vez. Essas chamadas são normalmente realizadas dentro de um loop de while.Utilize a propriedade NodeType para obter o tipo (por exemplo, atributo, comentário, elemento e assim por diante) do nó atual. |
| Skip | Ignore os filhos do nó atual e mova para o próximo nó. |
| MoveToContent e MoveToContentAsync | Ignore nós que não sejam de conteúdo e mova para o próximo nó de conteúdo ou para o final do arquivo. Os nós que não são de conteúdo incluem ProcessingInstruction, DocumentType, Comment, Whitespacee SignificantWhitespace. Os nós de conteúdo incluem texto sem espaço em branco, CDATA, EntityReference e EndEntity. |
| ReadSubtree | Leia um elemento e todos os seus filhos, e retorne uma nova instância XmlReader configurada como ReadState.Initial. Este método é útil para criar limites em torno de elementos XML; Por exemplo, se você deseja passar dados para outro componente para processamento e deseja limitar a quantidade de dados que o componente pode acessar. |
Consulte a página de referência XmlReader.Read para obter um exemplo de navegação por um fluxo de texto um nó de cada vez e exibição do tipo de cada nó.
As seções a seguir descrevem como você pode ler tipos específicos de dados, como elementos, atributos e dados digitados.
Ler elementos XML
A tabela a seguir lista os métodos e propriedades que a classe XmlReader fornece para elementos de processamento. Depois que o XmlReader é posicionado num elemento, as propriedades do nó, como Name, refletem os valores do elemento. Além dos membros descritos abaixo, qualquer um dos métodos e propriedades gerais da classe XmlReader também pode ser usado para processar elementos. Por exemplo, você pode usar o método ReadInnerXml para ler o conteúdo de um elemento.
Observação
Consulte a seção 3.1 do W3C XML 1.0 Recommendation para obter definições de tags de início, tags de fim e tags de elemento vazio.
| Use este membro XmlReader | Para |
|---|---|
| IsStartElement método | Verifique se o nó atual é uma marca de início ou uma tag de elemento vazia. |
| ReadStartElement método | Verifique se o nó atual é um elemento e avance o leitor para o próximo nó (chamadas IsStartElement seguidas por Read). |
| ReadEndElement método | Certifique-se de que o nó atual é um "tag de encerramento" e avance para o próximo nó. |
| ReadElementString método | Leia um elemento de apenas texto. |
| ReadToDescendant método | Avance o leitor XML para o próximo elemento descendente (filho) que tem o nome especificado. |
| ReadToNextSibling método | Avance o leitor XML para o próximo elemento irmão que tem o nome especificado. |
| IsEmptyElement propriedade | Verifique se o elemento atual tem uma tag de elemento final. Por exemplo: - <item num="123"/> (IsEmptyElement é true.)- <item num="123"> </item> (IsEmptyElement é false, embora o conteúdo do elemento esteja vazio.) |
Para obter um exemplo de leitura do conteúdo de texto de elementos, consulte o método ReadString. O exemplo a seguir processa elementos usando um loop 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
Ler atributos XML
Os atributos XML são mais comumente encontrados em elementos, mas também são permitidos na declaração XML e nos nós de tipo de documento.
Quando posicionado em um nó de elemento, o método MoveToAttribute permite que você percorra a lista de atributos do elemento. Observe que, após MoveToAttribute ter sido chamado, as propriedades do nó, como Name, NamespaceURIe Prefix refletem as propriedades desse atributo, não as propriedades do elemento ao qual o atributo pertence.
A classe XmlReader fornece esses métodos e propriedades para ler e processar atributos em elementos.
| Use este membro XmlReader | Para |
|---|---|
| HasAttributes propriedade | Verifique se o nó atual tem algum atributo. |
| AttributeCount propriedade | Obtenha o número de atributos no elemento atual. |
| MoveToFirstAttribute método | Mover para o primeiro atributo em um elemento. |
| MoveToNextAttribute método | Mover para o próximo atributo em um elemento. |
| MoveToAttribute método | Mover para um atributo especificado. |
| GetAttribute método ou Item[Int32] propriedade | Obtenha o valor de um atributo especificado. |
| IsDefault propriedade | Verifique se o nó atual é um atributo que foi gerado a partir do valor padrão definido no DTD ou no esquema. |
| MoveToElement método | Mover para o elemento que possui o atributo atual. Use esse método para retornar a um elemento depois de navegar por seus atributos. |
| ReadAttributeValue método | Analise o valor do atributo em um ou mais nós Text, EntityReferenceou EndEntity. |
Qualquer um dos métodos e propriedades gerais XmlReader também pode ser usado para processar atributos. Por exemplo, depois que o XmlReader é posicionado em um atributo, as propriedades Name e Value refletem os valores do atributo. Você também pode usar qualquer um dos métodos de conteúdo Read para obter o valor do atributo.
Este exemplo usa a propriedade AttributeCount para navegar por todos os atributos em um elemento .
// 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
Este exemplo usa o método MoveToNextAttribute em um loop de while para navegar pelos atributos.
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
Lendo atributos em nós de declaração XML
Quando o leitor XML é posicionado num nó de declaração XML, a propriedade Value retorna as informações de versão, independência e codificação como uma única string. XmlReader objetos criados pelo método Create, a classe XmlTextReader e a classe XmlValidatingReader expõem os itens versão, autónomo e codificação como atributos.
Lendo atributos em nós de tipo de documento
Quando o leitor XML está posicionado num nó de tipo de documento, o método GetAttribute e a propriedade Item[Int32] podem ser utilizadas para retornar os valores dos literais SYSTEM e PUBLIC. Por exemplo, chamar reader.GetAttribute("PUBLIC") retorna o valor PUBLIC.
Leitura de atributos em nós de instrução de processamento
Quando o XmlReader é posicionado em um nó de instrução de processamento, a propriedade Value retorna todo o conteúdo do texto. Os itens no nó de instrução de processamento não são tratados como atributos. Eles não podem ser lidos com o método GetAttribute ou MoveToAttribute.
Ler conteúdo XML
A classe XmlReader inclui os seguintes membros que leem o conteúdo de um arquivo XML e retornam o conteúdo como valores de cadeia de caracteres. (Para retornar tipos CLR, consulte Converter para tipos CLR.)
| Use este membro XmlReader | Para |
|---|---|
| Value propriedade | Obtenha o conteúdo de texto do nó atual. O valor retornado depende do tipo de nó; consulte a página de referência Value para obter detalhes. |
| ReadString método | Obtenha o conteúdo de um elemento ou nó de texto como uma cadeia de caracteres. Este método para no processamento de instruções e comentários. Para obter detalhes sobre como esse método lida com tipos de nó específicos, consulte a página de referência ReadString. |
| métodos ReadInnerXml e ReadInnerXmlAsync | Obtenha todo o conteúdo do nó atual, incluindo a formatação, mas excluindo as tags de início e fim. Por exemplo, para:<node>this<child id="123"/></node>ReadInnerXml retorna: this<child id="123"/> |
| métodos ReadOuterXml e ReadOuterXmlAsync | Obtenha todo o conteúdo do nó atual e seus filhos, incluindo marcação e tags de início/fim. Por exemplo, para:<node>this<child id="123"/></node>ReadOuterXml retorna: <node>this<child id="123"/></node> |
Converter para tipos CLR
Você pode usar os membros da classe XmlReader (listados na tabela a seguir) para ler dados XML e retornar valores como tipos CLR (Common Language Runtime) em vez de cadeias de caracteres. Esses membros permitem que você obtenha valores na representação mais apropriada para sua tarefa de codificação sem ter que analisar ou converter manualmente valores de cadeia de caracteres.
Os métodos ReadElementContentAs só podem ser chamados em tipos de nó de elemento. Esses métodos não podem ser usados em elementos que contenham elementos filho ou conteúdo misto. Quando chamado, o objeto XmlReader lê a marca inicial, lê o conteúdo do elemento e passa pela marca do elemento final. As instruções de processamento e os comentários são ignorados e as entidades são expandidas.
Os métodos ReadContentAs lêem o conteúdo do texto na posição de leitor atual e, se os dados XML não tiverem nenhuma informação de esquema ou tipo de dados associada aos dados, convertem o conteúdo do texto para o tipo de retorno solicitado. Texto, espaço vazio, espaço vazio significativo e seções CDATA são juntados. Comentários e instruções de processamento são ignorados e as referências de entidade são resolvidas automaticamente.
A classe XmlReader usa as regras definidas pelo W3C XML Schema Part 2: Datatypes recommendation.
| Use este método XmlReader | Para retornar este tipo de CLR |
|---|---|
| ReadContentAsBoolean e ReadElementContentAsBoolean | Boolean |
| ReadContentAsDateTime e ReadElementContentAsDateTime | DateTime |
| ReadContentAsDouble e ReadElementContentAsDouble | Double |
| ReadContentAsLong e ReadElementContentAsLong | Int64 |
| ReadContentAsInt e ReadElementContentAsInt | Int32 |
| ReadContentAsString e ReadElementContentAsString | String |
| ReadContentAs e ReadElementContentAs | O tipo que especifica com o parâmetro returnType |
| ReadContentAsObject e ReadElementContentAsObject | O tipo mais apropriado, tal como especificado pela propriedade XmlReader.ValueType. Consulte Type Support nas classes System.Xml para obter informações de mapeamento. |
Se um elemento não puder ser facilmente convertido em um tipo CLR devido ao seu formato, você poderá usar um mapeamento de esquema para garantir uma conversão bem-sucedida. O exemplo a seguir usa um arquivo .xsd para converter o elemento hire-date para o tipo xs:date e, em seguida, usa o método ReadElementContentAsDateTime para retornar o elemento como um objeto DateTime.
Entrada (hireDate.xml):
<employee xmlns="urn:empl-hire">
<ID>12365</ID>
<hire-date>2003-01-08</hire-date>
<title>Accountant</title>
</employee>
Esquema (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>
Código :
// 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
Saída:
Six Month Review Date: 7/8/2003 12:00:00 AM
Programação assíncrona
A maioria dos métodos XmlReader tem contrapartes assíncronas que têm "Async" no final de seus nomes de método. Por exemplo, o equivalente assíncrono de ReadContentAsObject é ReadContentAsObjectAsync.
Os seguintes métodos podem ser usados com chamadas de método assíncronas:
- GetAttribute
- MoveToAttribute
- MoveToFirstAttribute
- MoveToNextAttribute
- MoveToElement
- ReadAttributeValue
- ReadSubtree
- ResolveEntity
As seções a seguir descrevem o uso assíncrono para métodos que não têm contrapartidas assíncronas.
método 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
método 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
do método 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
método 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
do método 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
Considerações de segurança
Considere o seguinte ao trabalhar com a classe XmlReader:
As exceções lançadas do XmlReader podem divulgar informações de caminho que poderá não querer que sejam propagadas para a sua aplicação. Seu aplicativo deve capturar exceções e processá-las adequadamente.
Não habilite o processamento DTD se estiver preocupado com problemas de negação de serviço ou se estiver lidando com fontes não confiáveis. O processamento DTD é desabilitado por padrão para XmlReader objetos criados pelo método Create.
Se você tiver o processamento DTD habilitado, poderá usar o XmlSecureResolver para restringir os recursos que o XmlReader pode acessar. Você também pode projetar seu aplicativo para que o processamento XML tenha restrição de memória e tempo. Por exemplo, pode configurar limites de tempo na sua aplicação ASP.NET.
Os dados XML podem incluir referências a recursos externos, como um arquivo de esquema. Por padrão, os recursos externos são resolvidos usando um objeto XmlUrlResolver sem credenciais de usuário. Você pode proteger isso ainda mais seguindo um destes procedimentos:
Restrinja os recursos que o XmlReader pode acessar definindo a propriedade XmlReaderSettings.XmlResolver como um objeto XmlSecureResolver.
Não permita que o XmlReader abra recursos externos definindo a propriedade XmlReaderSettings.XmlResolver como
null.
Os sinalizadores de validação ProcessInlineSchema e ProcessSchemaLocation de um objeto XmlReaderSettings não são definidos por padrão. Isso ajuda a proteger o XmlReader contra ataques baseados em esquema quando ele está processando dados XML de uma fonte não confiável. Quando esses flags estão ativados, o XmlResolver do objeto XmlReaderSettings é utilizado para resolver localizações de esquema encontradas no documento de instância no XmlReader. Se a propriedade XmlResolver estiver definida como
null, os locais do esquema não serão resolvidos, mesmo que os sinalizadores de validação ProcessInlineSchema e ProcessSchemaLocation estejam definidos.Os esquemas adicionados durante a validação adicionam novos tipos e podem alterar o resultado da validação do documento que está sendo validado. Como resultado, os esquemas externos só devem ser resolvidos a partir de fontes confiáveis.
Recomendamos desativar o sinalizador ProcessIdentityConstraints ao validar documentos XML grandes e não confiáveis em cenários de alta disponibilidade em um esquema que tenha restrições de identidade em uma grande parte do documento. Esse sinalizador está habilitado por padrão.
Os dados XML podem conter um grande número de atributos, declarações de namespace, elementos aninhados e assim por diante que exigem uma quantidade substancial de tempo para serem processados. Para limitar o tamanho da entrada que é enviada para o XmlReader, você pode:
Limite o tamanho do documento definindo a propriedade MaxCharactersInDocument.
Limite o número de caracteres resultantes da expansão de entidades definindo a propriedade MaxCharactersFromEntities.
Crie uma implementação de
IStreampersonalizada para o XmlReader.
O método ReadValueChunk pode ser usado para lidar com grandes fluxos de dados. Esse método lê um pequeno número de caracteres de cada vez em vez de alocar uma única cadeia de caracteres para o valor inteiro.
Ao ler um documento XML com um grande número de nomes locais, namespaces ou prefixos exclusivos, pode ocorrer um problema. Se você estiver usando uma classe que deriva de XmlReadere chamar a propriedade LocalName, Prefixou NamespaceURI para cada item, a cadeia de caracteres retornada será adicionada a um NameTable. A coleção mantida pelo NameTable nunca diminui de tamanho, criando uma fuga de memória na memória virtual dos manipuladores de cadeia de caracteres. Uma atenuação para isso é derivar da classe NameTable e impor uma cota de tamanho máximo. (Não há como impedir o uso de um NameTable, ou mudar o NameTable quando ele está cheio). Outra mitigação é evitar o uso das propriedades mencionadas e, em vez disso, usar o método MoveToAttribute com o método IsStartElement sempre que possível; Esses métodos não retornam strings e, portanto, evitam o problema de encher demais a coleção de NameTable.
XmlReaderSettings objetos podem conter informações confidenciais, como credenciais de usuário. Um componente não confiável pode usar o objeto XmlReaderSettings e suas credenciais de usuário para criar objetos XmlReader para ler dados. Tenha cuidado ao armazenar em cache XmlReaderSettings objetos ou ao passar o objeto XmlReaderSettings de um componente para outro.
Não aceite componentes de suporte, como objetos NameTable, XmlNamespaceManagere XmlResolver, de uma fonte não confiável.