2010-02-26 32 views
52

tengo este código:uso de LINQ to XML con espacios de nombres XML

/*string theXml = 
@"<Response xmlns=""http://myvalue.com""><Result xmlns:a=""http://schemas.datacontract.org/2004/07/My.Namespace"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><a:TheBool>true</a:TheBool><a:TheId>1</a:TheId></Result></Response>";*/ 

string theXml = @"<Response><Result><TheBool>true</TheBool><TheId>1</TheId></Result></Response>"; 

XDocument xmlElements = XDocument.Parse(theXml); 

var elements = from data in xmlElements.Descendants("Result") 
       select new { 
          TheBool = (bool)data.Element("TheBool"), 
          TheId = (int)data.Element("TheId"), 
          }; 

foreach (var element in elements) 
{ 
    Console.WriteLine(element.TheBool); 
    Console.WriteLine(element.TheId); 
} 

Cuando utilizo el primer valor para theXml, el resultado es nulo, mientras que con el segundo, tengo buenos valores ...

¿Cómo usar Linq en Xml con valores xmlns?

Respuesta

79

LINQ a los métodos basados ​​en XML como Descendants y Element tomar una XName como argumento. Hay una conversión de string a XName que está sucediendo automáticamente para usted. Puede solucionar esto agregando un XNamespace antes de las cadenas en sus llamadas Descendants y Element. Ten cuidado porque tienes 2 espacios de nombres diferentes en el trabajo.

 

string theXml = 
       @"true1"; 

      //string theXml = @"true1"; 

    XDocument xmlElements = XDocument.Parse(theXml); 
    XNamespace ns = "http://myvalue.com"; 
    XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace"; 
    var elements = from data in xmlElements.Descendants(ns + "Result") 
      select new 
       { 
        TheBool = (bool) data.Element(nsa + "TheBool"), 
        TheId = (int) data.Element(nsa + "TheId"), 
       }; 

    foreach (var element in elements) 
    { 
     Console.WriteLine(element.TheBool); 
     Console.WriteLine(element.TheId); 
    } 
 

Aviso el uso de ns en Descendants y la NSA en Elements

+1

genial, funcionando :) !! Muchas gracias – Tim

+18

xmlElements.Descendants (xmlElements.Root.GetDefaultNamespace() + "Result") también puede funcionar ... –

23

Puede pasar un XName con un espacio de nombre a Descendants() y Element(). Cuando pasa una cadena a Descendants(), se convierte implícitamente en un XName sin espacio de nombres.

Para crear un XName en un espacio de nombres, cree un XNamespace y conéctelo al elemento local-name (una cadena).

XNamespace ns = "http://myvalue.com"; 
XNamespace nsa = "http://schemas.datacontract.org/2004/07/My.Namespace"; 

var elements = from data in xmlElements.Descendants(ns + "Result") 
        select new 
           { 
            TheBool = (bool)data.Element(nsa + "TheBool"), 
            TheId = (int)data.Element(nsa + "TheId"), 
           }; 

También hay una forma abreviada para crear un XName con un espacio de nombres a través de la conversión implícita de la cadena.

var elements = from data in xmlElements.Descendants("{http://myvalue.com}Result") 
        select new 
           { 
            TheBool = (bool)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheBool"), 
            TheId = (int)data.Element("{http://schemas.datacontract.org/2004/07/My.Namespace}TheId"), 
           }; 

Alternativamente, puede consultar contra XElement. Name.LocalName.

var elements = from data in xmlElements.Descendants() 
        where data.Name.LocalName == "Result" 
+0

LocalName no existe en mi intellissense – Tim

+2

que la conversión del operador + para XName es pardo, horrible y una abominación absoluta. ¿En qué estaba pensando MS? Presumiblemente, usa una expresión > debajo del capó, me hace sentir mal. – Gusdor

+0

+1 para la {taquigrafía}. ¡No sabía sobre eso! –

0

me encontré con el siguiente código para que funcione bien para leer los atributos con espacios de nombres en VB.NET:

MyXElement.Attribute(MyXElement.GetNamespaceOfPrefix("YOUR_NAMESPACE_HERE") + "YOUR_ATTRIB_NAME") 

Espero que esto ayude alguien en el camino.

0

Tengo varios espacios de nombres enumerados en la parte superior de un documento XML, realmente no me preocupan los elementos de qué espacio de nombres. Solo quiero obtener los elementos por sus nombres. He escrito este método de extensión.

/// <summary> 
    /// A list of XElement descendent elements with the supplied local name (ignoring any namespace), or null if the element is not found. 
    /// </summary> 
    public static IEnumerable<XElement> FindDescendants(this XElement likeThis, string elementName) { 
     var result = likeThis.Descendants().Where(ele=>ele.Name.LocalName==elementName); 
     return result; 
    } 
Cuestiones relacionadas