Search code examples
c#xml-parsinglinq-to-xmlxmldocumentxdoc

Querying XMLelements in C#


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


Solution

  • 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"