2

Given the code:

  var doc = new XmlDocument();
  doc.LoadXml(@"<a>
                    <b>test
                        <c>test2</c>
                    </b>
                </a>");
  var node = doc.SelectNodes("/a/b")[0];

I want to then extract the 'text' value of node b - in this case "test", without retrieving all text elements from all child nodes (as .innerText does)

I find myself resorting to this code

 var elementText = node.ChildNodes.Cast<XmlNode>().First(a => a.NodeType == XmlNodeType.Text).Value;

As unfortunately node.Value does something else in this case

is there a neater/inbuilt way without resorting to linq casting? that doesnt involve me doing something like;

foreach (var childNode in node.ChildNodes)
   if (childNode.NodeType==XmlNodeType.Text)
    ...
maxp
  • 24,209
  • 39
  • 123
  • 201

3 Answers3

4

I prefer XDocument to XmlDocument, I think it's easier to work with. You can easily get a value using the Element method to find the "b" element, and then using the Value property.

using(var stream = new MemoryStream())
{
    using(var streamWriter = new StreamWriter(stream))
    {
        streamWriter.Write(@"<a>
                                 <b>test
                                     <c>test2</c>
                                 </b>
                             </a>");
        streamWriter.Flush();
        streamWriter.BaseStream.Seek(0, SeekOrigin.Begin);
        var doc = XDocument.Load(stream);
        Console.WriteLine(doc.Element("a").Element("b").FirstNode.ToString());
    }
}

EDIT: As noted in comments, that would get the incorrect value. I've updated it correctly.

Dave Zych
  • 21,581
  • 7
  • 51
  • 66
  • agreed, on .Net 3.5 up there is no reason to use `XmlDocument`. – Jodrell Sep 27 '12 at 15:53
  • There's nothing _wrong_ with it, I think it's just preferred. Here's a good SO link describing the differences between XDocument and XmlDocument: http://stackoverflow.com/questions/1542073/xdocument-or-xmldocument – Dave Zych Sep 27 '12 at 16:00
  • It does not get "test", it get "test\ntest2" – cuongle Sep 27 '12 at 16:18
0

You want to use node.InnerText instead of Value. So you would have this:

 foreach(XmlNode child in node.ChildNodes)
 {
    if (string.IsNullOrEmpty(s))
    {
        s = child.InnerText;
    }
    else
    {
        s = s.Replace(child.InnerText, "");
    }
 }

   s.Trim();
Jetti
  • 2,418
  • 1
  • 17
  • 25
  • no dude, thats going to concat all child text elements aswell, so i would get `testtest2`. I've clarified my question. – maxp Sep 27 '12 at 15:43
0

In LINQ2XML you can do this

foreach(XNode elm in doc.Descendants("b").OfType<XText>())
{
//elm has the text
}
Anirudha
  • 32,393
  • 7
  • 68
  • 89