Подтвердить что ты не робот

Как получить значение XElement, а не значение всех дочерних узлов?

Пример xml:

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

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

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

4b9b3361

Ответ 1

При поиске текстовых данных в элементе <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);
}

Обновление:, если все, что вам нужно, это первый текст node, если он есть, вот пример, использующий вызовы метода 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() будет перечисляться только до тех пор, пока не будет найдено совпадение.

Ответ 2

Вы можете объединить значение всех узлов 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

msdn говорит:

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

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

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

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

Ответ 4

Удивительно, что кодер где-то в Microsoft думал, что возвращение всех текстовых значений в виде конкатенированной и неподписанной строки было бы полезно. К счастью, другой разработчик MS написал расширение XElement, чтобы вернуть то, что они называют "Мелкое значение" текста node здесь. Для тех, кто заставляет кисти щелкнуть по ссылкам, функция ниже...

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

Ответ 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);