0

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

  • Try following : List freeText = doc.Descendants("freeText").Where(x => (string)x.Element("informationType") == "47").ToList(); – jdweng Nov 25 '19 at 12:07

2 Answers2

2

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"
EylM
  • 5,967
  • 2
  • 16
  • 28
  • what if it doesn't have Sibling ? such as the example when informationType equals 47 –  Nov 25 '19 at 11:50
  • Sibling of the node. In all examples you provided, it contains the sibling. If in some case it would not have, then the SelectSingleNode will return null. – EylM Nov 25 '19 at 11:53
  • thank you for the effort, but it is returning a Null, (System.NullReferenceException) ? –  Nov 26 '19 at 10:20
  • I used your XML and added a root element. Please check if you might have namespaces in the full xml. – EylM Nov 26 '19 at 10:26
  • yes the xml in my question were just part of full xml, where can i locate it and handle it in the path ? –  Nov 26 '19 at 10:36
  • working code is var doc = new XmlDocument(); doc.LoadXml(XMLfile); XmlNamespaceManager xmlns = new XmlNamespaceManager(doc.NameTable); xmlns.AddNamespace("ns", "xml name space"); var res = doc.SelectSingleNode("//ns:textInfo/ns:freeText[ns:informationType='47']/following-sibling::ns:freeText", xmlns); thanks @EyIM –  Nov 26 '19 at 12:10
0

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();
Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • it didn't work, it returned a count of 0, probably it would work with one xml but not the others as it isn't all the same. –  Nov 26 '19 at 05:10