-->

How to get XElement's value and not value of a

2019-01-11 22:08发布

问题:

Sample xml:

<parent>
<child>test1</child>
<child>test2</child>
</parent>

If I look for parent.Value where parent is XElement, I get "test1test2". What I am expecting is "". (since there is no text/value for .

What property of XElement should I be looking for?

回答1:

When looking for text data in the <parent> element you should look for child nodes that have NodeType properties equal to XmlNodeType.Text. These nodes will be of type XText. The following sample illustrates this:

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);
}

Update: if all you want is the first Text node, if any, here's an example using LINQ method calls instead of query comprehension syntax:

var firstTextNode = p.Nodes().OfType<XText>().FirstOrDefault();
if (firstTextNode != null)
{
    var textValue = firstTextNode.Value;
    ...do something interesting with the value
}

Note: using First() or FirstOrDefault() will be more performant than Count() > 0 in this scenario. Count always enumerates the whole collection while FirstOrDefault() will only enumerate until a match is found.



回答2:

You could concatenate the value of all XText nodes in 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!"

For comparison:

// parent.Value  ==  "Hellotest1Worldtest2!"

// (parent.HasElements ? "" : parent.Value)  ==  ""


回答3:

It is amazing that a coder somewhere at Microsoft thought that returning all text values as a concatenated and undelimited string would be useful. Luckily, another MS developer wrote an XElement extension to return what they call the "Shallow Value" of the text node here. For those who get the willies from clicking on links, the function is below...

    public static string ShallowValue(this XElement element)
    {
        return element
               .Nodes()
               .OfType<XText>()
               .Aggregate(new StringBuilder(),
                          (s, c) => s.Append(c),
                          s => s.ToString());
    }

And you call it like this, because it gives you all the whitespace too (or, come to think of it, you could trim it in the extension, whatever)

// element is a var in your code of type XElement ...
string myTextContent = element.ShallowValue().Trim();


回答4:

msdn says:

A String that contains all of the text content of this element. If there are multiple text nodes, they will be concatenated.

So the behaviour is to be expected.

You could solve your problem by doing:

string textContent = parent.HasElements ? "" : parent.Value;


回答5:

// 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);


标签: c# xelement