c# - nombre - ¿Cómo obtener el valor de XElement y no el valor de todos los nodos secundarios?
obtener nombre nodo xml c# (5)
Muestra xml:
<parent>
<child>test1</child>
<child>test2</child>
</parent>
Si busco parent.Value donde parent es XElement, obtengo "test1test2". Lo que estoy esperando es "". (ya que no hay texto / valor para.
¿Qué propiedad de XElement debería estar buscando?
Cuando busque datos de texto en el elemento <parent>
, debe buscar nodos secundarios que tengan propiedades de NodeType
iguales a XmlNodeType.Text
. Estos nodos serán del tipo XText
. El siguiente ejemplo ilustra esto:
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);
}
Actualización: si todo lo que desea es el primer nodo de Texto, si lo hubiera, aquí hay un ejemplo que utiliza las llamadas al método LINQ en lugar de la sintaxis de comprensión de consulta:
var firstTextNode = p.Nodes().OfType<XText>().FirstOrDefault();
if (firstTextNode != null)
{
var textValue = firstTextNode.Value;
...do something interesting with the value
}
Nota: el uso de First()
o FirstOrDefault()
tendrá más rendimiento que Count() > 0
en este escenario. Count
siempre enumera toda la colección, mientras que FirstOrDefault()
solo lo hará hasta que se encuentre una coincidencia.
Es sorprendente que un programador en algún lugar de Microsoft pensara que devolver todos los valores de texto como una cadena concatenada y no delimitada sería útil. Afortunadamente, otro desarrollador de MS escribió una extensión XElement para devolver lo que ellos llaman el "Valor superficial" del nodo de texto here . Para aquellos que obtienen los willies haciendo clic en los enlaces, la función está debajo ...
public static string ShallowValue(this XElement element)
{
return element
.Nodes()
.OfType<XText>()
.Aggregate(new StringBuilder(),
(s, c) => s.Append(c),
s => s.ToString());
}
Y lo llamas así, porque también te da todo el espacio en blanco (o, ahora que lo pienso, podrías recortarlo en la extensión, como sea)
// element is a var in your code of type XElement ...
string myTextContent = element.ShallowValue().Trim();
Podría concatenar el valor de todos los nodos XText
en el 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!"
Para comparacion:
// parent.Value == "Hellotest1Worldtest2!"
// (parent.HasElements ? "" : parent.Value) == ""
msdn dice:
Una cadena que contiene todo el contenido de texto de este elemento. Si hay varios nodos de texto, serán concatenados.
Así que el comportamiento es de esperar.
Podrías resolver tu problema haciendo:
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);