2

I have different xml files and would like to get one specific value from each xml. what i'm trying to do is to search some of the elements in the xml and then when there is specific value or reference, then get the value of this reference. for example one xml has this:

<textInfo>
 <freeText>
  <informationType>15</informationType>
 </freeText>
</textInfo>
<textInfo>
 <freeText>
  <textSubject>4</textSubject>
  <informationType>47</informationType>
 </freeText>
  <freeText>some text</freeText>
</textInfo>
<textInfo>
 <freeText>
  <informationType>733</informationType>
  <status>1</status>
 </freeText>
</textInfo>

other xml has more than that, for example:

<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>15</informationType>
    <status>0</status>
  </freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>47</informationType>
  </freeText>
  <freeText>some text</freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <status>0</status>
  </freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>61</informationType>
  </freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>39</informationType>
  </freeText>
  <freeText>some text</freeText>
  <freeText>some other text</freeText>
</textInfo>

so what i tried to do is to first find the Length and how many tags in the xml and then use Foreach or While and then IF statement where tag equals 39 then get the value of the freeText tag

foreach (search all <textInfo>)
{
 if (<informationType> ==39)
   {
     do get the value of <freeText> of that <informationType>
   }
}

my problem is i don't know which to use in this case, should i use Foreach or while. and how to use it.

Note: i'm only getting the xml from webservice. i'm not storing it somewhere or have it as xml file. i'm just handling all the xml in my project and only stuck on this searching multiple tags to find one value

EDIT/update i have tried below two codes but both are returning a Null value

XmlDocument doc = new XmlDocument();
doc.LoadXml(requestInterceptor.LastResponseXML);

foreach (XmlNode node in doc.SelectNodes("//textInfo/freeText[informationType>=39]/informationType"))
  {
   Object.Type = node.InnerText;
  }

other code:

XDocument doc1 = XDocument.Parse(requestInterceptor.LastResponseXML);
var query = doc1.Descendants("textInfo").Where(ft => ((int?)ft.Element("informationType")).Equals("39"));
from c in doc1.Root.Descendants("textInfo")
where (c.Attribute("informationType").Equals("39"))
select c.Element("freeText");
Object.Type = query.ToString();
  • [Linq to XML](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/linq-to-xml-overview) can help you to query the content of the file in an easy way. But your structure is not fixed (freeText sometimes has a string or other fields) so I could become a mess to work with ... – lordvlad30 Nov 20 '19 at 08:55
  • https://stackoverflow.com/questions/642293/how-do-i-read-and-parse-an-xml-file-in-c – Marat Isaw Nov 20 '19 at 08:59
  • thank you @lordvlad30, but i'm only getting the xml from webservice. i'm not storing it somewhere or have it as xml file. i'm just handling all the xml in my project and only stuck on this searching multiple tags to find one value –  Nov 20 '19 at 09:07
  • @Ghaly_m you can use the Linq to XML without having the file, like Jon Skeet said in his comment. – lordvlad30 Nov 20 '19 at 09:26

2 Answers2

4

LINQ to XML makes this sort of query simple. I believe you're trying to find all <freeText> elements which have a direct <informationType> child element with a value of 39. Assuming every <informationType> element actually contains an integer, you could use:

XDocument doc = ...;
var freeTextsWithInfoType39 = doc
    .Descendants("freeText")
    .Where(ft => ((int?) ft.Element("informationType")) == 39);

You can then use that however you want - perhaps with another query to transform the results, or a foreach loop.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • is there a way to use this without the LINQtoXML as i don't have the XML file stored with me, i'm only getting it from a webservice and reading it and trying to get the required values. –  Nov 20 '19 at 09:11
  • @Ghaly_m: I don't understand - if you've got the XML, it doesn't matter *where* you got it from, you can still load it into an `XDocument`. If you've got it as a string, just use `XDocument doc = XDocument.Parse(text);` for example. – Jon Skeet Nov 20 '19 at 09:13
  • it is returning a Null... XDocument doc1 = XDocument.Parse(requestInterceptor.LastResponseXML); var query = doc1.Descendants("textInfo").Where(ft => ((int?)ft.Element("informationType")).Equals("39")); from c in doc1.Root.Descendants("textInfo") where (c.Attribute("informationType").Equals("39")) select c.Element("freeText"); –  Nov 25 '19 at 09:01
  • @Ghaly_m: That's not what the query was in my answer though. I looked for `freeText` elements which have a child `informationType` element with a value of 39, and I also didn't compare an *integer* with a *string*. The query that's actually in my answer finds a single `freeText` element. To get the `informationType` element, just ask for the parent. – Jon Skeet Nov 25 '19 at 09:22
  • my mistake, i edit it based on the answer, the exact code of yours returns System.Linq.Enumerable+WhereEnumerableIterator`1[System.Xml.Linq.XElement] –  Nov 25 '19 at 09:47
  • @Ghaly_m: Well yes, that's a sequence of `freeText` elements. So then do whatever you want with those elements, e.g. via a foreach loop. – Jon Skeet Nov 25 '19 at 10:01
1

In addition to using XDocument, you can also use XmlDocument and XPath.

 XmlDocument doc = new XmlDocument();
 doc.Load(@"sample.xml");

 foreach(XmlNode node in doc.SelectNodes("//textInfo/freeText[informationType>=39]/informationType"))
 {
      Console.WriteLine(node.InnerText);
 }
 //the print out should be:
 //47
 //61
 //39

For more infomation about XPath, please refer to:https://www.w3schools.com/xml/xpath_intro.asp

The sample xml string doesn't have a root element, if you want to load such xml string, you should format the xml string first.

var xml = @"<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>15</informationType>
    <status>0</status>
  </freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>47</informationType>
  </freeText>
  <freeText>some text</freeText>
</textInfo>"
var validXml = $"<resp>{xml}</resp>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(validXml);
//The other code is the same as before.
xiangbin.pang
  • 319
  • 1
  • 7
  • i have tried the following but it is returning a Null ..... XmlDocument doc = new XmlDocument(); doc.LoadXml(requestInterceptor.LastResponseXML); foreach (XmlNode node in doc.SelectNodes("//textInfo/freeText[informationType>=39]/informationType")) { EMD_Object.infoType = node.InnerText; } –  Nov 25 '19 at 08:55
  • @mylahg hi, mylahg, I just update my answer, I think you can refer to the latest answer. – xiangbin.pang Nov 26 '19 at 00:54