Querying XMLelements in C#

336 views Asked by At

I have many complex XML files that I would like to query and search to get one value, below are two shortened example:

1

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

2

<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>15</informationType>
    <status>0</status>
  </freeText>
</textInfo>
<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>47</informationType>
  </freeText>
  <freeText>My required 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>

required output is: the text inside the tag <freeText> (My required text) where tag <informationType> = (47)

have tried multiple linq to xml codes but none of them worked for me. ex.

Code1

var query = from q in XDocument.Parse(requestInterceptor.LastResponseXML)
    .Descendants("freeText")
    where (bool)q.Element("informationType").Equals("47")
    select q.Element("freeText").Value;

Code2

XDocument doc = XDocument.Parse(requestInterceptor.LastResponseXML); ;
    var q = doc
    .Descendants("freeText[1]")
    .Where(ft => ((int?)ft.Element("informationType")) == 47);
Object.Type = q.ToString();

Code3

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

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

Code4

XmlDocument doc2 = new XmlDocument();
                    doc.LoadXml(requestInterceptor.LastResponseXML);
                    foreach (XmlNode node in doc2.SelectNodes("//textInfo/freeText[informationType>=47]/informationType"))
                    {
                        Object.Type = node.InnerText;
                    }

Note: i'm only getting the xml from webservice. i'm not storing it somewhere or have it as xml file. also note that this is part of the xml where only i needed to get the information

2

There are 2 answers

6
EylM On BEST ANSWER

You need to get the sibling element of the selected freeText element. You can use XPATH query with a proper namespace:

var doc = new XmlDocument(); doc.LoadXml(XMLfile); 
var xmlns = new XmlNamespaceManager(doc.NameTable); 
xmlns.AddNamespace("ns", "your_namespace"); 
var res = doc.SelectSingleNode("//ns:textInfo/ns:freeText[ns:informationType='47']/following-sibling::ns:freeText", xmlns);     
Console.Write(res.InnerText);

Output:

My required text

Update (as requested in the comments):

Sibling node is the node immediately following the selected node in the same tree level.

Second example:

<textInfo>
  <freeText>
    <textSubject>4</textSubject>
    <informationType>47</informationType>
  </freeText>
  <freeText>My required text</freeText>
</textInfo>

The code above is doing following:

  1. Selecting the first freeText node where informationType equals 47.
  2. The first sibling node of the select freeText, is freeFree text with "My required text"
1
Athanasios Kataras On

You can try the following (I just assumed that you have root element, otherwise it wouldn't work for you.

Check fiddle here

    string input = @"<root>
        <textInfo>
            <freeText>
                <informationType>15</informationType>
            </freeText>
        </textInfo>
        <textInfo>
            <freeText>
                <textSubject>4</textSubject>
                <informationType>47</informationType>
            </freeText>
            <freeText>My required text</freeText>
        </textInfo>
        <textInfo>
            <freeText>
                <informationType>733</informationType>
                <status>1</status>
            </freeText>
        </textInfo>
    </root>";

    var doc = XDocument.Parse(input);


    var freeTexts = doc.Descendants("textInfo")
        .Where(tf => tf.Element("freeText").Element("informationType") != null &&
               tf.Element("freeText").Element("informationType").Value.Equals("47") &&
               tf.Elements("freeText").Count() > 1)
        .Select(tf => tf.Elements("freeText").Skip(1).Single().Value).ToList();