Значение XElement в C#

Как получить значение XElement без получения дочерних элементов?

Пример:

<?xml version="1.0" ?>
<someNode>
    someValue
    <child>1</child>
    <child>2</child>
</someNode>

Если я использую XElement.Value для <someNode>, я получаю строку "somevalue<child>1</child><child>2<child>", но я хочу получить только «какое-то значение» без подстроки "<child>1</child><child>2<child>".


person shadeglare    schedule 11.07.2010    source источник


Ответы (3)


Вы можете сделать это немного проще, чем использовать Descendants — метод Nodes возвращает только прямые дочерние узлы:

XElement element = XElement.Parse(
    @"<someNode>somevalue<child>1</child><child>2</child></someNode>");
var firstTextValue = element.Nodes().OfType<XText>().First().Value;

Обратите внимание, что это будет работать даже в том случае, когда дочерние элементы появились перед текстовым узлом, например:

XElement element = XElement.Parse(
    @"<someNode><child>1</child><child>2</child>some value</someNode>");
var firstTextValue = element.Nodes().OfType<XText>().First().Value;
person Jon Skeet    schedule 11.07.2010
comment
Если я хочу получить значение всех узлов, мне нужно обязательно перебирать список узлов? Меня интересуют значения узлов не типа XText - person Ramón García-Pérez; 20.02.2013
comment
@BBHorus: Ну, если вы хотите просмотреть все узлы, то да, вам нужно перебрать их. На самом деле неясно, что вы пытаетесь сделать - вы можете добавить новый вопрос. - person Jon Skeet; 20.02.2013
comment
О, неважно, теперь я понял, что мне нужны некоторые текстовые узлы, но первый и последний. У меня есть этот элемент: ‹package›package ‹name›com‹/name›.‹name›sample‹/name›.‹name›app1‹/name›;‹/package› Мне нужно такое значение: com .sample.app1, я думаю, мне нужно использовать какое-то регулярное выражение или что-то еще, например, перебирать дочерние узлы и получать только элементы, пропуская первый и последний. - person Ramón García-Pérez; 20.02.2013
comment
@BBHorus: Вы почти конечно не должны использовать регулярное выражение. Это почти всегда неправильный подход к обработке XML. - person Jon Skeet; 20.02.2013
comment
Не к XML относится к значению в элементе XML, оно всегда содержит эти две части: начинается с package и заканчивается ; те, которые я не хочу, но все остальное. Спасибо за разъяснения и помощь - person Ramón García-Pérez; 20.02.2013

Прямого пути нет. Вам придется повторить и выбрать. Например:

var doc = XDocument.Parse(
    @"<someNode>somevalue<child>1</child><child>2</child></someNode>");
var textNodes = from node in doc.DescendantNodes()
                where node is XText
                select (XText)node;
foreach (var textNode in textNodes)
{
    Console.WriteLine(textNode.Value);
}
person John Saunders    schedule 11.07.2010
comment
Большое спасибо. В моей программе мне нужно полное перечисление узлов xml и изменение всех значений. С вашим образцом я не нужен в рекурсивном перечислении узлов xml. - person shadeglare; 12.07.2010
comment
@MaxFX: это все равно будет рекурсивно перечислять все узлы внутри элемента. Это скрыто, но это все еще происходит. Смотрите мой ответ, чтобы избежать этого. - person Jon Skeet; 12.07.2010
comment
Вы можете просто написать var textNodes = doc.DescendantNodes().OfType‹XText›(); - person Porkopek; 17.07.2016

Я думаю, что вы хотите, чтобы это был первый узел-потомок, поэтому что-то вроде:

var value = XElement.Descendents.First().Value;

Где XElement — это элемент, представляющий ваш элемент <someNode>.

Вы можете специально запросить первый текстовый элемент (который является «каким-то значением»), поэтому вы также можете сделать:

var value = XElement.Descendents.OfType<XText>().First().Value;
person ckramer    schedule 11.07.2010