Como ler o grande arquivo XML sem carregá -lo na memória e usar o Xelement
-
20-09-2019 - |
Pergunta
Eu quero ler um arquivo XML grande (100+m). Devido ao seu tamanho, não quero carregá -lo na memória usando o Xelement. Estou usando consultas Linq-xml para analisar e ler.
Qual é a melhor maneira de fazer isso? Algum exemplo sobre combinação de XPath ou XMLReader com Linq-xml/Xelement?
Por favor ajude. Obrigado.
Solução
Sim, você pode combinar o XMLReader com o método xnode.readfrom, consulte o exemplo na documentação que usa C# para processar os nós seletivamente encontrados pelo XMLReader como um Xelement.
Outras dicas
O código de exemplo na documentação do MSDN para o XNode.ReadFrom
O método é o seguinte:
class Program
{
static IEnumerable<XElement> StreamRootChildDoc(string uri)
{
using (XmlReader reader = XmlReader.Create(uri))
{
reader.MoveToContent();
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "Child")
{
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
break;
}
}
}
}
static void Main(string[] args)
{
IEnumerable<string> grandChildData =
from el in StreamRootChildDoc("Source.xml")
where (int)el.Attribute("Key") > 1
select (string)el.Element("GrandChild");
foreach (string str in grandChildData)
Console.WriteLine(str);
}
}
Mas eu descobri que o StreamRootChildDoc
O método no exemplo precisa ser modificado da seguinte forma:
static IEnumerable<XElement> StreamRootChildDoc(string uri)
{
using (XmlReader reader = XmlReader.Create(uri))
{
reader.MoveToContent();
// Parse the file and display each of the nodes.
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Child")
{
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
else
{
reader.Read();
}
}
}
}
Lembre -se de que você terá que ler o arquivo sequencialmente e se referir a irmãos ou descendentes será lento, na melhor das hipóteses, na pior das hipóteses. Caso contrário, @martinhonnn tem a chave.