LINQ to XML - 获取给定XElement的文本内容,而不包括子元素的文本内容

8

我刚刚开始使用LINQ to XML,但是我遇到了一个问题:如何获取给定XElement的文本内容而不包括所有子元素的文本内容。

举个例子,如果我有以下XML文档:

<?xml version="1.0" encoding="utf-8" ?>
<root xmlns="example.org/rootns">This is root value
    <children>
        <child name='child 1'>value 1</child>
        <child name='child 2'>value 2
            <grandchild name='grandchild A'>value A</grandchild>
        </child>
    </children>
</root>

我使用以下的测试方法:

private static void Test()
{
    string xString = @"<?xml version=""1.0"" encoding=""utf-8"" ?><root xmlns=""example.org/rootns"">This is root value<children><child name='child 1'>value 1</child><child name='child 2'>value 2<grandchild name='grandchild A'>value A</grandchild></child></children></root>";

    var xDoc = XDocument.Parse(xString);

    XNamespace ns = @"example.org/rootns";
    string elemName = "child";

    var xElems = from e in xDoc.Descendants(ns + elemName)
                 select e;

    foreach (var xElem in xElems)
    {
        Console.WriteLine(xElem.Value);
    }
}

然后,我会在输出中得到两行:
    value 1
    value 2value A

第一行显示了第一个子元素的内容 - 这是可以的。但第二行不仅显示了第一个子元素的文本内容,还包括该子元素的任何后代的文本内容。
如何只获取第二个子元素的文本内容,而不包括其孙子节点的文本内容?
还要注意,示例只是一个简单的例子,用于说明我正在做什么,在实际生产中,我可能不知道子元素的名称(如果有的话),但我应该能够获取所需的元素以获取文本内容。
Jon Skeet的答案帮助了解决方案。只需使用以下方法替换foreach循环即可选择文本XNode而不是XElement的值:
...
foreach (var xElem in xElems)
{
    var values = from n in xElem.Nodes()
                 where n.NodeType == System.Xml.XmlNodeType.Text
                 select n;

    if (values != null && values.Count() > 0)
        Console.WriteLine(values.First());
}
1个回答

8

如果有多个文本节点,您想要做什么?例如,您可以将它们全部连接在一起:

var text = string.Join("", element.Nodes.OfType<XText>().Select(x => x.Value));

编辑:如果你只需要一个元素,那么比你展示的更简单:

var textNode = xElem.Nodes().OfType<XText>().FirstOrDefault();
if (textNode != null)
{
    Console.WriteLine(textNode.Value);
}

那让我找对了方向。我不希望在每个元素中有多个文本节点,所以我只会取第一个。我会编辑我的问题,展示类似于你的例子的解决方案。谢谢。 - Avery
@Avery:如果你只想要第一个节点,可以看一下我的编辑,里面有更简单的方法。 - Jon Skeet
第二个片段稍作更正:Nodes() 被定义为方法,而不是属性,所以代码应该写成:var textNode = xElem.Nodes().OfType<XText>().FirstOrDefault(); - JeffFerguson
@JeffFerguson:已修复 - 当然,你也可以自己进行这样的更改。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接