示例 xml:
<parent>
<child>test1</child>
<child>test2</child>
</parent>
如果我寻找 parent.Value,其中 parent 是 XElement,我会得到“test1test2”。我期待的是“”。(因为 .
我应该寻找 XElement 的什么属性?
在<parent>
元素中查找文本数据时,您应该查找NodeType
属性等于XmlNodeType.Text
. 这些节点的类型为XText
. 以下示例说明了这一点:
var p = XElement
.Parse("<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
var textNodes = from c in p.Nodes()
where c.NodeType == XmlNodeType.Text
select (XText)c;
foreach (var t in textNodes)
{
Console.WriteLine(t.Value);
}
更新:如果您想要的只是第一个 Text 节点(如果有的话),这里有一个使用 LINQ 方法调用而不是查询理解语法的示例:
var firstTextNode = p.Nodes().OfType<XText>().FirstOrDefault();
if (firstTextNode != null)
{
var textValue = firstTextNode.Value;
...do something interesting with the value
}
注意:使用First()
orFirstOrDefault()
将比Count() > 0
在这种情况下更高效。Count
总是枚举整个集合,而FirstOrDefault()
只会枚举直到找到匹配项。
您可以连接所有XText
节点的值parent
:
XElement parent = XElement.Parse(
@"<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
string result = string.Concat(
parent.Nodes().OfType<XText>().Select(t => t.Value));
// result == "HelloWorld!"
为了比较:
// parent.Value == "Hellotest1Worldtest2!"
// (parent.HasElements ? "" : parent.Value) == ""
令人惊讶的是,微软某处的编码人员认为将所有文本值作为连接且未定界的字符串返回会很有用。幸运的是,另一位 MS 开发人员编写了一个 XElement 扩展来返回他们所谓的此处文本节点的“浅值” 。对于那些通过点击链接获得威利的人,功能如下......
public static string ShallowValue(this XElement element)
{
return element
.Nodes()
.OfType<XText>()
.Aggregate(new StringBuilder(),
(s, c) => s.Append(c),
s => s.ToString());
}
你这样称呼它,因为它也给了你所有的空白(或者,想想看,你可以在扩展中修剪它,无论如何)
// element is a var in your code of type XElement ...
string myTextContent = element.ShallowValue().Trim();
msdn说:
包含此元素的所有文本内容的字符串。如果有多个文本节点,它们将被连接起来。
所以这种行为是可以预料的。
您可以通过以下方式解决您的问题:
string textContent = parent.HasElements ? "" : parent.Value;
// Create the XElement
XElement parent = XElement.Parse(
@"<parent>Hello<child>test1</child>World<child>test2</child>!</parent>");
// Make a copy
XElement temp=new XElement(parent);
// remove all elements but root
temp.RemoveNodes();
// now, do something with temp.value, e.g.
Console.WriteLine(temp.value);