tags:

views:

80

answers:

6

Suppose I have some XmlElement; let's call it element. If I want to get all of the child nodes of that element, I can call element.ChildNodes. If I want the text of the element and all its children, then I can go with element.InnerText.

However, suppose I have some XML that looks like this:

<TopElement attr1="value1" attr2="value2">
    This is the text I want.
    <ChildElement1>This is text I don't want.</ChildElement1>
    <ChildElement2>This is more text I don't want.</ChildElement2>
</TopElement>

If I go with element.InnerText, what I get is this:

This is the text I want.This is text I don't want.This is more text I don't want.

If I want just the text within TopElement but NOT any of its children, I can do this:

Dim txt As String
For Each child As Xml.XmlNode In XmlElement.ChildNodes
    If TypeOf child Is Xml.XmlText Then
        txt = child.InnerText
        Exit For
    End If
Next

But this seems quite silly to me. Surely there is a better way?

EDIT: Sorry I didn't specify this initially: I'm looking for a solution not involving LINQ (we're in the Dark Ages over here with .NET 2.0).

A: 

use linq to xml

e-turhan
wow, specific...an example would probably be of help
Pondidum
I'm actually looking for something non-LINQ. I've specified that now in my question. Thanks, though.
Dan Tao
+2  A: 

Technically, the text within the TopElement is a childnode.

class Program
{
    static string xml = @"<Top>Text<child/><child/></Top>";

    static void Main(string[] args)
    {
        XmlDocument xdoc = new XmlDocument();
        xdoc.LoadXml(xml);

        Console.WriteLine(xdoc.DocumentElement.ChildNodes[0].Value);

        Console.ReadLine();
    }
}
bryanbcook
The main problem I see with this answer is that it assumes ChildNodes[0] will be text. I don't know for sure that there will be top-level text; I want to see IF there is, and if so, to get it.
Dan Tao
Absolutely. I don't see anything wrong with the solution you've provided above. InnerText takes the text of all childnodes. If you want the text of a specific childNode, you will have to iterate through them to find it.
bryanbcook
+1  A: 
Dim txt As String

If TypeOf XmlElement.FirstChild Is Xml.XmlText Then
        txt = XmlElement.FirstChild.InnerText
End If
najmeddine
I like this answer; however, it does assume that if there is top-level text, it will be the first child. Consider something like this: <elem1><elem2>Unwanted text</elem2>Wanted text</elem1>. In this case your code would miss the wanted text.
Dan Tao
if the text can be anywhere between child nodes, an iteration is needed and your solution is great.
najmeddine
+2  A: 
XmlDocument document = new XmlDocument();
document.LoadXml(yourXml);

//Find the first child whos type is XmlText
var nodeYouWant = document.DocumentElement.ChildNodes.OfType<System.Xml.XmlText>().FirstOrDefault();

Edit

Since you can't use LINQ, you can still use the good ol' XQuery and request the node text

XmlNode nodeYouWant = document.DocumentElement.SelectSingleNode("./text()");

This will work even if the text you want is between the two child nodes.

Pierre-Alain Vigeant
+2  A: 

You can use an XPath expression that specifically looks for a text node (sorry for the C#)

XmlText text = doc.SelectSingleNode("/TopElement/text()") as XmlText;
if (text != null)
{
    Console.WriteLine(text.Value);
}

(Where doc is an XmlDocument containing your XML)

Peter van der Heijden
This is exactly what I was looking for. Nice!
Dan Tao
A: 

Here is an example that will give you the request text:

static void Main(string[] args)
        {
            var document = XDocument.Load("../../TestXmlFile.xml");

            if(document.Root == null) return; 

            var text = ((XText) document.Root.FirstNode).Value; 

            Console.WriteLine(text);

        }
azamsharp