0

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 Answers2

0

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);
        }
    }

}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • I am able to get the xelement. But each ProductName has many name tags. If I use FirstOrDefault() i only get the first value. i want to know if minimum one name tag in the ProductName has the value "car". If yes i want that Particular ProductDetails data as a whole in a seperate xml file @jdweng –  May 05 '20 at 09:07
0
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.

Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49