Qual a melhor forma de usar XPath com grandes arquivos XML em .NET?

votos
17

Eu preciso fazer algum processamento em bastante grandes arquivos XML (grande aqui sendo potencialmente mais de um gigabyte) em C # incluindo a realização de algumas consultas XPath complexos. O problema que tenho é que a forma padrão que eu normalmente fazer isso através das bibliotecas System.xml gosta de carregar o arquivo inteiro na memória antes que ele faz qualquer coisa com ele, o que pode causar problemas de memória com arquivos desse tamanho.

Eu não preciso estar atualizando os arquivos em tudo apenas lê-los e consultar os dados contidos neles. Algumas das consultas XPath são bastante envolvidos e atravessar vários níveis de relação tipo pai-filho - Eu não tenho certeza se isso vai afetar a capacidade de usar um leitor de fluxo em vez de carregar os dados na memória como um bloco.

Uma maneira que eu posso ver de fazê-lo funcionar é realizar a análise simples usando uma abordagem baseada em fluxo e talvez envolvendo as instruções XPath em XSLT transformações que eu poderia percorrem os arquivos mais tarde, embora pareça um pouco complicado.

Alternadamente eu sei que existem alguns elementos que as consultas XPath não vai se deparar, então eu acho que eu poderia quebrar o documento em uma série de fragmentos menores com base em sua estrutura original árvore, que poderia, talvez, ser pequeno o suficiente para processar na memória sem causando muito estrago.

Eu tentei explicar o meu objetivo aqui, então se eu estou latindo totalmente a árvore errada em termos de abordagem geral eu tenho certeza que as pessoas podem me pôs certo ...

Publicado 02/01/2009 em 17:39
fonte usuário
Em outras línguas...                            


10 respostas

votos
0

Você tem tentado XPathDocument? Esta classe é otimizado para lidar com consultas XPath eficiente.

Se você não consegue lidar com seus documentos de entrada de forma eficiente usando XPathDocument você pode considerar o pré-processamento e / ou dividir seus documentos de entrada usando um XmlReader.

Respondeu 02/01/2009 em 17:48
fonte usuário

votos
1

Você já delineou suas escolhas já.

Ou você precisa de abandonar o XPath e uso XmlTextReader ou você precisa quebrar o documento em pedaços gerenciáveis ​​sobre os quais você pode usar XPath.

Se você escolher o último uso XPathDocument sua restrição somente leitura permite melhor utilizado de memória.

Respondeu 02/01/2009 em 17:49
fonte usuário

votos
1

Para realizar consultas XPath com as classes .NET padrão da árvore do documento inteiro precisa ser carregado na memória que pode não ser uma boa idéia se ele pode levar até um gigabyte. IMHO o XmlReader é uma boa classe para lidar com tais tarefas.

Respondeu 02/01/2009 em 17:49
fonte usuário

votos
1

Parece que você já tentou usar XPathDocumente não poderia acomodar o documento XML analisado na memória .

Se este for o caso, antes de começar a dividir o arquivo (que é em última instância a decisão certa!), Você pode tentar usar o Saxon processador XSLT / XQuery. Ele tem uma representação muito eficiente em memória de um documento XML carregado (o modelo "tinytree" ). Além disso Saxon SA (a versão shema-aware, que não é livre) tem algumas extensões de streaming . Leia mais sobre isso aqui .

Respondeu 02/01/2009 em 18:27
fonte usuário

votos
1

Como apenas cerca de ler a coisa toda em um banco de dados e, em seguida, trabalhar com o banco de dados temporário? Isso pode ser melhor, porque então suas consultas pode ser feito de forma mais eficiente usando TSQL.

Respondeu 02/01/2009 em 19:38
fonte usuário

votos
2

arquivos XML Gigabyte! Eu não invejo essa tarefa.

Existe alguma maneira que os arquivos podem ser enviados em uma maneira melhor? Por exemplo, eles estão sendo enviados através da rede para você - se eles são, então, um formato mais eficiente poderia ser melhor para todos os interessados. Lendo o arquivo em um banco de dados não é uma má idéia, mas poderia ser muito demorado, de fato.

Eu não iria tentar e fazer tudo na memória, lendo o arquivo inteiro - a menos que você tem um SO de 64 bits e muita memória. E se o arquivo torna-se 2, 3, 4 GB?

Uma outra abordagem poderia ser a de ler o arquivo XML e usar SAX para analisar o arquivo e escrever arquivos XML menores de acordo com alguma divisão lógica. Você poderia, então, processar estes com XPath. Eu usei XPath em arquivos 20-30MB e é muito rápido. I foi originalmente indo para usar SAX, mas pensei que eu iria dar XPath um ir e ficou surpreso quão rápido foi. Eu salvou um monte de tempo de desenvolvimento e, provavelmente, só perdeu 250ms por consulta. Eu estava usando Java para minha análise, mas eu suspeito que não haveria pouca diferença em .NET.

Eu li que XML :: Twig (Módulo Perl CPAN) foi escrito explicitamente para lidar com SAX base de análise XPath. você pode usar um idioma diferente?

Isso também pode ajudar a https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-1044772.html

Respondeu 03/01/2009 em 11:46
fonte usuário

votos
1

Eu acho que a melhor solução é fazer o seu próprio parser XML que pode ler pequenos pedaços e não todo o arquivo, ou você pode dividir o arquivo grande em arquivos pequenos e usar classes dotnet com esses arquivos. O problema é que você não pode analisar alguns dos dados até que todo os dados estão disponíveis, então eu recomendo usar o seu próprio não parser aulas dotnet

Respondeu 03/01/2009 em 12:14
fonte usuário

votos
9

XPathReader é a resposta. Não é parte do C # tempo de execução, mas está disponível para download da Microsoft. Aqui está um artigo do MSDN .

Se você construir um XPathReader com um XmlTextReader você começa a eficiência de um streaming de ler com a conveniência de expressões XPath.

Eu não usei-o em arquivos de tamanho gigabyte, mas eu tê-lo usado em arquivos que são dezenas de megabytes, que normalmente é suficiente para abrandar soluções DOM base.

Citando o seguinte: "O XPathReader fornece a capacidade de executar XPath em documentos XML de uma forma de streaming".

Baixar de Microsoft

Respondeu 04/04/2009 em 07:44
fonte usuário

votos
0

Uma vez que em seu caso o tamanho dos dados pode ser executado em Gbs você considerou usando ADO.NET com XML como um banco de dados. Além de que o consumo de memória não seria enorme.

Outra abordagem seria usar LINQ to XML com o uso de elementos como XElementStream. Espero que isto ajude.

Respondeu 19/03/2010 em 20:11
fonte usuário

votos
2

http://msdn.microsoft.com/en-us/library/bb387013.aspx tem um exemplo relevante alavancar XStreamingElement.

Respondeu 16/02/2011 em 10:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more