web-dev-qa-db-fra.com

Utiliser Linq to XML avec des espaces de noms XML

J'ai ce code:

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

Quand j'utilise la première valeur pour theXml, le résultat est nul, alors qu'avec la seconde, j'ai de bonnes valeurs ...

Comment utiliser Linq to Xml avec les valeurs xmlns?

56
Tim

Les méthodes LINQ to XML telles que Descendants et Element prennent un XName comme argument. Il y a une conversion de string à XName qui se produit automatiquement pour vous. Vous pouvez résoudre ce problème en ajoutant XNamespace avant les chaînes de vos appels Descendants et Element. Attention, vous avez 2 espaces de nom différents au travail.


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

Notez l'utilisation de ns dans Descendants et de nsa dans Elements

86
Mike Two

Vous pouvez passer un XName avec un espace de nom à Descendants () et Element () . Lorsque vous passez une chaîne à Descendants (), elle est implicitement convertie en un XName sans espace de nom.

Pour créer un XName dans un espace de noms, vous créez un XNamespace et vous le concaténez avec l'élément local-name (une chaîne).

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

Il existe également une forme abrégée permettant de créer un XName avec un espace de nom via une conversion implicite à partir de chaîne.

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

Vous pouvez également interroger XElement. Name.LocalName .

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

Plusieurs espaces de noms sont répertoriés dans la partie supérieure d'un document XML. Peu m'importe quels éléments appartiennent à quel espace de noms. Je veux juste obtenir les éléments par leurs noms. J'ai écrit cette méthode d'extension.

    /// <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

J'ai trouvé que le code suivant fonctionnait correctement pour la lecture d'attributs avec des espaces de noms dans VB.NET:

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

J'espère que cela aide quelqu'un sur la route.

0
dotNET