Estou tentando ler o seguinte documento Xml o mais rápido que posso e permitir que classes adicionais gerenciem a leitura de cada sub-bloco.
<ApplicationPool>
<Accounts>
<Account>
<NameOfKin></NameOfKin>
<StatementsAvailable>
<Statement></Statement>
</StatementsAvailable>
</Account>
</Accounts>
</ApplicationPool>
No entanto, estou tentando usar o objeto XmlReader para ler cada conta e, posteriormente, o "StatementsAvailable". Você sugere usar XmlReader.Read e verificar cada elemento e manipulá-lo?
Eu pensei em separar minhas classes para lidar com cada nó corretamente. Portanto, há uma classe AccountBase que aceita uma instância XmlReader que lê o NameOfKin e várias outras propriedades sobre a conta. Então eu queria interagir com as declarações e deixar outra classe se informar sobre a declaração (e subsequentemente adicioná-la a um IList).
Até agora, eu tenho a parte "por classe" feita executando XmlReader.ReadElementString (), mas não consigo treinar como dizer ao ponteiro para mover para o elemento StatementsAvailable e deixar-me iterar por eles e deixar outra classe ler cada uma dessas propriedades .
Parece fácil!
Respostas:
Minha experiência
XmlReader
é que é muito fácil ler acidentalmente demais. Eu sei que você disse que queria ler o mais rápido possível, mas você tentou usar um modelo DOM? Descobri que o LINQ to XML torna o trabalho com XML muito mais fácil.Se o seu documento for particularmente grande, você pode combinar um
XmlReader
LINQ to XML criando umXElement
de umXmlReader
para cada um dos seus elementos "externos" em um fluxo contínuo: isso permite que você faça a maior parte do trabalho de conversão em LINQ to XML, mas ainda só precisa uma pequena parte do documento na memória a qualquer momento. Aqui está um exemplo de código (ligeiramente adaptado desta postagem do blog ):Já usei isso para converter os dados do usuário StackOverflow (que são enormes) em outro formato antes - funciona muito bem.
EDIT do radarbob, reformatado por Jon - embora não esteja muito claro a qual problema "ler muito longe" está sendo referido ...
Isso deve simplificar o aninhamento e resolver o problema de "uma leitura longe demais".
Isso resolve o problema de "leitura muito longe" porque implementa o padrão clássico de loop while:
fonte
if(reader.Name == elementName)
parawhile(reader.Name == elementName)
corrigir o problema apontado por pbz?SimpleStreamAxis()
ignorará elementos quando o XML não estiver indentado, porqueNode.ReadFrom()
posiciona o leitor no próximo nó após o elemento carregado - que será ignorado pelo próximo incondicionalRead()
. Se o próximo nó for um espaço em branco, está tudo bem. Caso contrário, não. Para versões sem esse problema, veja aqui , aqui ou aqui .Três anos depois, talvez com a ênfase renovada nos dados WebApi e xml, me deparei com essa pergunta. Como estou inclinado a seguir Skeet para fora de um avião sem pára-quedas, e vendo seu código inicial duplamente corraborado pelo artigo da equipe MS Xml, bem como um exemplo na Transformação de streaming BOL de Large Xml Docs , rapidamente esqueci os outros comentários , mais especificamente de 'pbz', que apontou que, se você tiver os mesmos elementos por nome em sucessão, todos os outros serão ignorados devido à leitura dupla. E, de fato, os artigos do blog BOL e MS estavam analisando documentos de origem com elementos de destino aninhados mais profundamente do que o segundo nível, mascarando esse efeito colateral.
As outras respostas tratam desse problema. Eu só queria oferecer uma revisão um pouco mais simples que parece funcionar bem até agora e leva em consideração que o xml pode vir de fontes diferentes, não apenas um uri, e assim a extensão funciona no XmlReader gerenciado pelo usuário. A única suposição é que o leitor está em seu estado inicial, caso contrário, o primeiro 'Read ()' pode avançar além de um nó desejado:
fonte
else Read()
se aplique a ambos. Obrigado por pegar isso.Fazemos esse tipo de análise XML o tempo todo. A chave é definir onde o método de análise deixará o leitor na saída. Se você sempre deixar o leitor no próximo elemento após o elemento que foi lido primeiro, poderá ler de forma segura e previsível no fluxo XML. Portanto, se o leitor estiver indexando o
<Account>
elemento no momento, após a análise, o leitor indexará a</Accounts>
tag de fechamento.O código de análise é semelhante a este:
A
Statements
classe apenas lê no<StatementsAvailable>
nóA
Statement
classe seria muito parecidafonte
Para subobjetos,
ReadSubtree()
dá a você um leitor de xml limitado aos subobjetos, mas eu realmente acho que você está fazendo isso da maneira mais difícil. A menos que você tenha requisitos muito específicos para lidar com xml incomum / imprevisível, useXmlSerializer
(talvez junto com,sgen.exe
se realmente desejar).XmlReader
é ... complicado. Contrasta com:fonte
O exemplo a seguir navega pelo fluxo para determinar o tipo de nó atual e, em seguida, usa XmlWriter para gerar o conteúdo XmlReader.
O exemplo a seguir usa os métodos XmlReader para ler o conteúdo de elementos e atributos.
fonte
Você pode percorrer o xmlnode e obter os dados ...... Leitor C # XML
fonte
Não tenho experiência. Mas acho que o XmlReader é desnecessário. É muito difícil de usar.
O XElement é muito fácil de usar.
Se você precisa de desempenho (mais rápido), deve alterar o formato do arquivo e usar as classes StreamReader e StreamWriter.
fonte