Как прочитать большой xml-файл без загрузки его в память и использования XElement
-
20-09-2019 - |
Вопрос
Я хочу прочитать большой xml-файл (более 100 М).Из-за его размера я не хочу загружать его в память с помощью XElement.Я использую запросы linq-xml для их анализа и чтения.
Каков наилучший способ сделать это?Есть какой-нибудь пример сочетания XPath или XmlReader с linq-xml/XElement?
Пожалуйста, помогите.Спасибо.
Решение
Да, вы можете объединить XmlReader с метод XNode.readFrom из, смотрите пример в документации, который использует C # для выборочной обработки узлов, найденных XmlReader в качестве XElement.
Другие советы
Пример кода в документации MSDN для XNode.ReadFrom
способ заключается в следующем:
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);
}
}
Но я обнаружил, что StreamRootChildDoc
метод в примере необходимо изменить следующим образом:
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();
}
}
}
}
Просто имейте в виду, что вам придется читать файл последовательно, и обращение к братьям и сестрам или потомкам будет в лучшем случае медленным, а в худшем - невозможным.В противном случае ключ у @MartinHonnn.