Parse Big XML file using XMLReader

834 views Asked by At

I have a very big xml file with below format

<ABC>
  <NAMEDETAILS></NAMEDETAILS>
  <PRODUCT>
    <PRODUCTDETAILS>
      <ProductName>
         <name>Car</Name>
         <name>lorry<name>
         <name>Car<name>
      </ProductName>
    </PRODUCTDETAILS>
    <PRODUCTDETAILS>
      <ProductName>
         <name>van</Name>
         <name>cycle</Name>
         <name>bus</Name>
      </ProductName>
    </PRODUCTDETAILS>
    <PRODUCTDETAILS>
      <ProductName>
         <name>car</Name>
         <name>cycle</Name>
         <name>bus</Name>
      </ProductName>
    </PRODUCTDETAILS>
  <PRODUCT>    
</ABC>

I want to retrieve the PRODUCTDETAILS data whose name tag has the value "car" and save it in a new xml file. I am using XMLReader but i am stuck in moving forward. Can somebody help me. Below is the c# code

XMLReader xmlReader = XMLReader.Create(@"\\Drive\xmlfile.xml")
while (xmlReader.Read())
{
  If (xmlReader.NodeType == XMLNodeType.Element) && (xmlReader.Name == "PRODUCTDETAILS")
  {
    xmlReader.ReadtoDescendant("ProductName")
  }
}
2

There are 2 answers

1
jdweng On

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string INPUT_FILENAME = @"c:\temp\test.xml";
        const string OUTPUT_FILENAME = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(INPUT_FILENAME);

            string header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><Cars></Cars>";
            XDocument doc = XDocument.Parse(header);
            XElement cars = doc.Root;

            while (!reader.EOF)
            {
                if (reader.Name != "PRODUCTDETAILS")
                {
                    reader.ReadToFollowing("PRODUCTDETAILS");
                }
                if (!reader.EOF)
                {
                    XElement product = (XElement)XElement.ReadFrom(reader);
                    if(product.Descendants("name").Any(x => ((string)x).Trim() == "Car"))
                    {
                        cars.Add(product);
                    }

                }
            }
            doc.Save(OUTPUT_FILENAME);
        }
    }

}
0
Alexander Petrov On
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace ConApp1
{
    class Program
    {
        static void Main()
        {
            using (var xmlWriter = XmlWriter.Create("result.xml"))
            using (var xmlReader = XmlReader.Create("test.xml"))
            {
                xmlWriter.WriteStartElement("PRODUCT");

                while (xmlReader.ReadToFollowing("PRODUCTDETAILS"))
                {
                    using (var nodeReader = xmlReader.ReadSubtree())
                    {
                        nodeReader.MoveToContent();

                        var elem = (XElement)XNode.ReadFrom(nodeReader);

                        var name = elem.Descendants("name").First().Value;

                        if (name.Equals("car", StringComparison.OrdinalIgnoreCase))
                        {
                            elem.WriteTo(xmlWriter);
                        }
                    }
                }
            }
        }
    }
}

Since you say that the file is large, both reading and writing should be done using streaming tools. XmlWriter is used for writing. This guarantees low memory consumption and no OutOfMemoryException occurs.