1
votes

We have XML like so:

<Example>
  <Node>Some text here
    <ChildNode>Child 1</ChildNode>
    <ChildNode>Child 2</ChildNode>
  </Node>
</Example>

We are using XmlDocument to parse this.

When we have the XmlNode of the "Node" element, XmlNode.InnerText returns us this:

"Some text hereChild 1Child2"

How can we get the inner text of the Node element without the child nodes' inner text? We don't really want to use any RegEx or string splitting to accomplish this.

Note: We also don't want to switch to using a different set of classes to parse this XML, it would be too much of a code change.

4

4 Answers

6
votes
var doc = new XmlDocument();
doc.LoadXml(xml);
var text = doc.SelectSingleNode("Example/Node/text()").InnerText; // or .Value

returns

"Some text here\r\n    "

and text.Trim() returns

"Some text here"
1
votes

How about:

XmlDocument d=new XmlDocument();
d.LoadXml(@"<Example>
  <Node>Some text here
    <ChildNode>Child 1</ChildNode>
    <ChildNode>Child 2</ChildNode>
  </Node>
</Example>");
var textNodeValues=d.DocumentElement
    .FirstChild
    .ChildNodes
    .Cast<XmlNode>()
    .Where(x=>x.NodeType==XmlNodeType.Text)
    .Select(x=>x.Value);
1
votes

You can implement like:

    XmlDocument doc = new XmlDocument();
    doc.LoadXml("<Example><Node>Some text here<ChildNode>Child 1</ChildNode><ChildNode>Child 2</ChildNode></Node></Example>");
    XmlNode node = doc.SelectSingleNode( "Example/Node" );
    if (node.HasChildNodes)
    {
        string value = node.FirstChild.Value;
    }
1
votes

To my knowledge, there is no direct way to do that. You'll have to iterate over the child text nodes and build the concatenated text yourself:

using System.Text;
using System.Xml;

public string GetImmediateInnerText(XmlNode node)
{
    StringBuilder builder = new StringBuilder();
    foreach (XmlNode child in node.ChildNodes) {
        if (child.NodeType == XmlNodeType.Text) {
            builder.Append(child.Value);
        }
    }
    return builder.ToString();
}

You can also use the text() XPath expression, as @abatishchev does:

public string GetImmediateInnerText(XmlNode node)
{
    StringBuilder builder = new StringBuilder();
    foreach (XmlNode child in node.SelectNodes("text()")) {
        builder.Append(child.Value);
    }
    return builder.ToString();
}