Search code examples
c#xmlxmlreader

XmlReader - read child


I have a trouble with reading string (xml structure) using xmlReader.

string xml = @"
<Data>
  <Prices Id="16" Code="C3" >
     <Units>
       <Unit Id="17"/>
      </Units> 
  </Prices>
  <Units>
    <Unit Id="1" IsActive="true" />
    <Unit Id="2" IsActive="true" />
  </Units>
 <Product Id="16" Code="C3" >
      <Names>
       <Name NameVersion="1" Name="C3 " />
      </Names>
      <Units>
       <Unit Id="16"/>
      </Units>
 </Product>
</Data>
"

How could I read only Element "Units" with child's id 1 and 2 ?

Actually I tried parsing this string into XDocument.

var root = XElement.Parse(xmlFile);
var units = root.Elements("Units").FirstOrDefault();

and it works fine but I could work with really big xml and I don't want to parse all string into XDocument. I'm looking for method when I could load partly elements from a string. Also I tried do this using XmlTextReader but this not working in my case

using (XmlReader xmlTextReader = XmlReader.Create(new StringReader(xmlFile)))
        {
            if (xmlTextReader.ReadToFollowing(elementName))
            {
                bool isOnNode = xmlTextReader.ReadToDescendant(elementName);
                while (isOnNode)
                {
                    yield return XNode.ReadFrom(xmlTextReader) as XElement;
                    if (!xmlTextReader.IsStartElement(elementName))
                        isOnNode = xmlTextReader.ReadToNextSibling(elementName);
                }
            }
        }

Expected output: xElement =

<Units>
    <Unit Id="1" IsActive="true" />
    <Unit Id="2" IsActive="true" />
  </Units>

Solution

  • See below an example on how you can parse your xml using XmlReader. It iterates over all the nodes until it finds an Unit element. It then checks for the presence of the attribute value Id and parses the value of IsActive:

       public static void Main()
        {
            string xml = "<Data><Units><Unit Id=\"1\" IsActive=\"true\" /><Unit Id=\"2\" IsActive=\"true\" /></Units><Product Id=\"16\" Code=\"C3\" ><Names><Name NameVersion=\"1\" Name=\"C3 \" /></Names><Units><Unit Id=\"16\"/></Units></Product></Data>";
            var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
            XmlTextReader reader = new XmlTextReader(memoryStream);
    
            while (reader.Read())
            {
                //keep reading until we see a book element 
                if (reader.Name.Equals("Unit") &&
                    (reader.NodeType == XmlNodeType.Element))
                {
    
                    if (reader.GetAttribute("Id") == "1" || reader.GetAttribute("Id") == "2")
                    {
                        string isActive = reader.GetAttribute("IsActive");
                    }
                    else
                    {
                        reader.Skip();
                    }
                }
            }
        }