Intento obtener información de un archivo xml y hasta ahora soy bastante bueno con la navegación a través de
doc.Element("foo1").Element("foo2").Value Pero ahora me estoy topando con una pared y creo que es por el espacio de nombres. Uso este fragmento de código para filtrar una parte específica de mi doc xml:
XNamespace xmlns = "http://www.siemens.com/automation/Openness/SW/Interface/v4"; IEnumerable<XElement> de = from el in doc.Descendants(xmlns + "Section") where el.Attribute("Name").Value == "Input" select el;Se da el espacio de nombres y el XElement resultante es el siguiente:
<Section Name="Input" xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v4"> <Member Name="STARTTASTER" Datatype="Bool" Remanence="NonRetain" Accessibility="Public"> <AttributeList> <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserVisible" Informative="true" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserReadOnly" Informative="true" SystemDefined="true">false</BooleanAttribute> <BooleanAttribute Name="UserDeletable" Informative="true" SystemDefined="true">true</BooleanAttribute> </AttributeList> </Member> </Section> Eso es exactamente lo que quiero tener y puedo guardarlo en root
ahora uso
var foo = root.Element(xmlns + "Section"); Console.WriteLine(foo);Y esperaría conseguir esto
<Member Name="STARTTASTER" Datatype="Bool" Remanence="NonRetain" Accessibility="Public"> <AttributeList> <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserVisible" Informative="true" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserReadOnly" Informative="true" SystemDefined="true">false</BooleanAttribute> <BooleanAttribute Name="UserDeletable" Informative="true" SystemDefined="true">true</BooleanAttribute> </AttributeList> </Member>Pero no consigo nada. Ahora mi primera pregunta sería por qué y en segundo lugar, cómo podría lograr el resultado esperado.
También estaría feliz si hay una forma más agradable/más práctica. De hecho, quiero almacenar el valor "STARTTASTER" en una variable.
Pruebe la siguiente solución.
Guardé su XML como un archivo e:\Temp\Aschenauer.xml :
<Section Name="Input" xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v4"> <Member Name="STARTTASTER" Datatype="Bool" Remanence="NonRetain" Accessibility="Public"> <AttributeList> <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalVisible" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="ExternalWritable" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserVisible" Informative="true" SystemDefined="true">true</BooleanAttribute> <BooleanAttribute Name="UserReadOnly" Informative="true" SystemDefined="true">false</BooleanAttribute> <BooleanAttribute Name="UserDeletable" Informative="true" SystemDefined="true">true</BooleanAttribute> </AttributeList> </Member> </Section>C#
void Main() { const string filename = @"e:\Temp\Aschenauer.xml"; XDocument xdoc = XDocument.Load(filename); XNamespace ns = xdoc.Root.GetDefaultNamespace(); var NameAttr = xdoc.Descendants(ns + "Member") .Attributes("Name").FirstOrDefault().Value; Console.WriteLine($"Name='{NameAttr}'"); }Producción
Nombre = 'STARTTASTER'
Para responder a la pregunta específica "¿por qué no obtengo nada?" parte, en su código aquí:
root.Element(xmlns + "Section") root es un elemento de Section que obtuvo de la consulta inicial. El código anterior está buscando el primer elemento secundario llamado Section . No hay ninguno, por lo que obtienes null . Lo que parece estar buscando es el primer elemento secundario llamado Member :
root.Element(xmlns + "Member")