Как прочитать большой XML-файл, не загружая его в память и не используя XElement
Я хочу прочитать большой XML-файл (100+M). Из-за его размера я не хочу загружать его в память, используя XElement. Я использую запросы linq-xml для анализа и чтения.
Какой лучший способ сделать это? Какой-нибудь пример сочетания XPath или XmlReader с linq-xml/XElement?
Пожалуйста помоги. Благодарю.
3 ответа
Да, вы можете комбинировать 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 имеет ключ.