it-swarm.dev

Use Linq para Xml com namespaces Xml

Eu tenho este código:

/*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);
}

Quando eu uso o primeiro valor para o XML, o resultado é nulo, enquanto com o segundo, eu tenho bons valores ...

Como usar o Linq para Xml com valores xmlns?

56
Tim

O LINQ para métodos XML como Descendants e Element aceita uma XName como argumento. Existe uma conversão de string para XName que está acontecendo automaticamente para você. Você pode corrigir isso adicionando uma XNamespace antes das strings em suas chamadas Descendants e Element. Cuidado porque você tem dois namespaces diferentes no trabalho.


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

Observe o uso de ns em Descendants e nsa em Elements

86
Mike Two

Você pode passar um XName com um namespace para Descendants () e Element () . Quando você passa uma string para Descendants (), ela é implicitamente convertida em um XName sem namespace.

Para criar um XName em um namespace, crie um XNamespace e concatene-o ao elemento local-name (uma string).

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"),
                              };

Há também uma forma abreviada para criar um XName com um namespace por meio de conversão implícita de string.

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"),
                              };

Como alternativa, você pode consultar XElement. Name.LocalName .

var elements = from data in xmlElements.Descendants()
                   where data.Name.LocalName == "Result"
25
Lachlan Roche

Eu tenho vários namespaces listados no topo de um documento XML, eu realmente não me importo com quais elementos são de qual namespace. Eu só quero pegar os elementos pelos seus nomes. Eu escrevi este método de extensão.

    /// <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;
    }
2
mike nelson

Eu encontrei o seguinte código para funcionar bem para a leitura de atributos com namespaces no VB.NET:

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

Espero que isso ajude alguém abaixo da estrada.

0
dotNET