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?
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
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"
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;
}
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.