Используйте Linq to Xml с пространствами имен 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);
}
Когда я использую первое значение для theXml, результат равен нулю, тогда как со вторым я получаю хорошие значения...
Как использовать Linq to Xml со значениями xmlns?
4 ответа
LINQ to XML методы, такие как Descendants
а также Element
принять XName
в качестве аргумента. Есть преобразование из string
в XName
это происходит автоматически для вас. Вы можете исправить это, добавив XNamespace
до струн в вашем Descendants
а также Element
звонки. Остерегайтесь, потому что у вас есть 2 разных пространства имен на работе.
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 );
}
Обратите внимание на использование ns в Descendants
и нса в Elements
Вы можете передать XName с пространством имен в Descendants() и Element (). Когда вы передаете строку в Descendants(), она неявно преобразуется в XName без пространства имен.
Чтобы создать XName в пространстве имен, вы создаете XNamespace и присоединяете его к элементу local-name (строка).
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"),
};
Существует также сокращенная форма для создания XName с пространством имен посредством неявного преобразования из строки.
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"),
};
В качестве альтернативы, вы можете сделать запрос к XElement. Name.LocalName.
var elements = from data in xmlElements.Descendants()
where data.Name.LocalName == "Result"
У меня есть несколько пространств имен, перечисленных в верхней части XML-документа, меня не волнует, какие элементы из какого пространства имен. Я просто хочу получить элементы по их именам. Я написал этот метод расширения.
/// <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;
}
Я нашел следующий код, чтобы нормально работать для чтения атрибутов с пространствами имен в VB.NET:
MyXElement.Attribute(MyXElement.GetNamespaceOfPrefix("YOUR_NAMESPACE_HERE") + "YOUR_ATTRIB_NAME")
Надеюсь, что это поможет кому-то в будущем.