Как получить значение XElement, а не значение всех дочерних узлов? - PullRequest
25 голосов
/ 23 ноября 2010

Пример xml:

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

Если я ищу parent.Value, где parent - XElement, я получаю «test1test2». То, что я ожидаю, это "". (поскольку нет текста / значения для.

Какое свойство XElement мне нужно искать?

Ответы [ 5 ]

25 голосов
/ 23 ноября 2010

При поиске текстовых данных в элементе <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() или FirstOrDefault() будет более производительным, чем Count() > 0 в этом сценарии. Count всегда перечисляет всю коллекцию, а FirstOrDefault() будет перечислять только до тех пор, пока не будет найдено совпадение.

8 голосов
/ 23 ноября 2010

Вы можете объединить значения всех 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)  ==  ""
3 голосов
/ 02 октября 2017

Удивительно, что программист где-то в Microsoft думал, что было бы полезно вернуть все текстовые значения в виде объединенной и неограниченной строки. К счастью, другой разработчик 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();
1 голос
/ 19 декабря 2011
// 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);
1 голос
/ 23 ноября 2010

msdn говорит:

Строка, содержащая все текстовое содержимое этого элемента. Если текстовых узлов несколько, они будут объединены.

Так что поведение следует ожидать.

Вы можете решить свою проблему, выполнив:

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