adamo94
adamo94

Reputation: 517

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>

Upvotes: 1

Views: 464

Answers (2)

Alex
Alex

Reputation: 21766

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

Upvotes: 1

kain64b
kain64b

Reputation: 2326

XPathReader can help you. here you can find full article: https://msdn.microsoft.com/en-us/library/ms950778.aspx short example: using System; using System.Xml; using System.Xml.XPath; using GotDotNet.XPath;

public class Test{
static void Main(string[] args) {

      try{ 
XPathReader xpr  = new XPathReader("books.xml", "//book/title"); 

            while (xpr.ReadUntilMatch()) {
               Console.WriteLine(xpr.ReadString()); 
             }      
            Console.ReadLine(); 
   }catch(XPathReaderException xpre){
      Console.WriteLine("XPath Error: " + xpre);
      }catch(XmlException xe){
         Console.WriteLine("XML Parsing Error: " + xe);
      }catch(IOException ioe){
         Console.WriteLine("File I/O Error: " + ioe);
      }
   }  
}

Upvotes: 0

Related Questions