Good day, gentlemen! I really need your help, please help parse xml ..

<?xml version="1.0" encoding="utf-8"?> <users> <user name="Bill Gates" group="programmers"> <company>Microsoft</company> <age>48</age> </user> <user name="Larry Page" group="programmers"> <company>Google</company> <age>42</age> </user> <user name="Edward Norton" single="actor"> <company>NewLineCinema</company> <age>40</age> </user> </users> 

If the user attribute group attribute exists in the user tag, then we read all the blocks where group = programmers. And if it is not there, but there is a single element, then only this block is read. Thank you all in advance for your help!

  • If there is a single - then the record is one (first, define it), then read all the attributes (in the original attributes, much more, this simplified model). If there is a group, then the records are combined into one whole, and their attributes are also read. - dexploizer
  • With processing, I need to get the necessary data from it, but it does not work. - dexploizer

4 answers 4

You can use XPath queries and LINQ for XML.

Here is an example XPath. First you need to prepare your XML, for this you can use Stream objects, transfer to the URI constructor, or use the simplest XMLReader. In this case, for the sake of completeness, a MemoryStream is used, for the rest, see the description of XDocument.Load .

  string xml = @"<?xml version=""1.0"" encoding=""utf-8""?> <users> <user name=""Bill Gates"" group=""programmers""> <company>Microsoft</company> <age>48</age> </user> <user name=""Larry Page"" group=""programmers""> <company>Google</company> <age>42</age> </user> <user name=""Edward Norton"" single=""actor""> <company>NewLineCinema</company> <age>40</age> </user> </users> "; MemoryStream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)); XDocument xdoc = XDocument.Load(xmlStream); 

After the document is loaded, you can easily read the data using XPath queries. They can be quite flexible and complex, allowing you to handle multiple conditions in one line. Of the minuses, you'll have to learn XPath.

  var programmers = xdoc.Document.XPathSelectElements(@"./users/user[@group=""programmers""]"); var single = xdoc.Document.XPathSelectElements(@"./users/user[@single]"); var result = programmers.Count() > 0 ? programmers : single; 

UPD: sample data output to the console

  foreach (var res in result) { Console.WriteLine(""); Console.WriteLine(res.Element("company").Value); Console.WriteLine(res.Element("age").Value); Console.WriteLine(res.Attribute("name") != null ? res.Attribute("name").Value : ""); Console.WriteLine(res.Attribute("group") != null ? res.Attribute("group").Value : ""); } 
  • Thanks for the answer! Only .. how to get the value of single and programmers? Now they output C # code - dexploizer
  • @YuriGo, programmers are the value of an anttribute, and single is an attribute! What values ​​do you want from them? - koks_rs
  • @YuriGo, they return a collection of XElement elements from User , in the documentation you can see how to work with it. Possible options in the foreach(var res in result) output: res.Element("company").Value , res.Element("age").Value , res.Attribute("group") != null ? res.Attribute("group").Value : " " res.Attribute("group") != null ? res.Attribute("group").Value : " " , etc. and the like. - Alex Krass

You can use Linq to XML.

 IEnumerable<XElement> elementsProgrammers = xUsersParticipants .Element("users") .Elements("user") .Where(e => ((string)e.Attribute("group")) =="programmers").Select(i => i); if(elementsProgrammers.Count() == 0) { elementsProgrammers = xUsersParticipants .Element("users") .Elements("user") .Where(e => ((string)e.Attribute("group"))=="single") .Select(i => i); } foreach(XElement element in elementsProgrammers ) { Console.WriteLine(element); } 
  • Thank you! But, the answer is already found :) - dexploizer

based on what I understand in your question, you can do this:

  //Читаем документ XPathDocument doc = new XPathDocument("xml.xml"); XPathNavigator nav = doc.CreateNavigator(); //создаем запросы xpath XPathNodeIterator iterator = nav.Select(@"/users/user[@group=""programmers""]"); var programmers = iterator.OfType<XPathNavigator>().ToList(); iterator = nav.Select(@"/users/user[@single=""actor""]"); var single = iterator.OfType<XPathNavigator>().ToList(); var result = programmers.Any() ? programmers : single; foreach (var item in result) { Console.WriteLine(string.Format("Найден элемент :\n {0}", item.InnerXml)); } 

XPath examples

  • discovered XPath, thank you :) The only thing, for some reason, I realized that if there is a Single, then ONLY it should be considered, and it could have been easier to do with Doc. - xSx
  • @xSx, well maybe, if there is a Single, then only it needs to be counted, then of course you need to change the XPATH query, maybe I misunderstood the question) - koks_rs

If the forehead (stupid: D), you can

  XmlDocument doc = new XmlDocument(); doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?> <users> <user name=\"Bill Gates\" group=\"programmers\"> <company>Microsoft</company> <age>48</age> </user> <user name=\"Larry Page\" group=\"programmers\"> <company>Google</company> <age>42</age> </user> <user name=\"Edward Norton\" single=\"actor\"> <company>NewLineCinema</company> <age>40</age> </user> </users>"); bool ProgIn = false; foreach (XmlNode noda in doc.DocumentElement) { if (noda.LocalName == "user") { foreach (XmlAttribute atr in noda.Attributes) if (atr.Value == "programmers") { ProgIn = true; Console.WriteLine("Считываем везде где программерс"); } foreach (XmlAttribute atr in noda.Attributes) if (!ProgIn) if (atr.Name == "single") { Console.WriteLine("Считываем только сингл"); return; } } } Console.ReadKey(); 
  • Take as an example how to take the necessary nodes. You can definitely do it without a double cycle, so far, something I dread terribly, so I propose to suffer myself) - xSx
  • Thank you Well, if not stupid?) Are there any more elegant options :) - dexploizer