XPath / linq to xml: xmlns=""testNS"" не дает результата
xml файл / строка может быть проверен, но не дает результатов, если запрашивается XPath или linq to xml. Разница: xmlns=""testNS"" xsi:... в строках примера. Без этого xmlns=... это работает, а без этого нет (но это проверяет).
Следующая программа показывает проблему, которую я не понимаю: (VS2012)
using System;
using System.Linq;
using System.Xml.Linq;
namespace XmlNamespaceTest
{
class Program
{
static void Main(string[] args)
{
string xmlStringWithNs = GetStringWithNs();
bool resultWithNs = Test(xmlStringWithNs);
string xmlStringWithoutNs = GetStringWithoutNs();
bool resultWithoutNs = Test(xmlStringWithoutNs);
string xmlStringPlaying = GetModifiedNsForPlaying();
bool resultPlaying = Test(xmlStringPlaying);
Console.WriteLine("with ns: {0}", resultWithNs);
Console.WriteLine("without ns: {0}", resultWithoutNs);
Console.WriteLine("playing: {0}", resultPlaying);
Console.Read();
}
private static bool Test(string xmlString)
{
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var root = XElement.Parse(xmlString);
var es = root.Descendants("Event")
.Where(e => e.Attribute("serviceId").Value == "SERVICEID");
var list = es.ToList();
return list.Count > 0;
}
private static string GetModifiedNsForPlaying()
{
return
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<dataset xmlns=""testNS"" xsi:schemaLocation=""testNS Test.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<eventCommands>
<DEFINE><Event eventId=""EVENTID"" serviceId=""SERVICEID"" /></DEFINE>
</eventCommands>
</dataset>";
}
private static string GetModifiedNs()
{
return
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<dataset xmlns=""testNS"" xsi:schemaLocation=""testNS Test.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<eventCommands>
<DEFINE><Event eventId=""EVENTID"" serviceId=""SERVICEID"" /></DEFINE>
</eventCommands>
</dataset>";
}
/// <summary>
/// Does not contain: xmlns=""testNS""
/// Successfull!
/// </summary>
/// <returns>true if found, false else</returns>
private static string GetStringWithoutNs()
{
return
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<dataset xsi:schemaLocation=""Test.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<eventCommands>
<DEFINE><Event eventId=""EVENTID"" serviceId=""SERVICEID"" /></DEFINE>
</eventCommands>
</dataset>";
}
/// <summary>
/// GetStringWithNs
///
/// Does contain: xmlns=""testNS""
/// NOT Successfull!
/// Validation against an xsd succeeds.
/// </summary>
/// <returns>true if found, false else</returns>
private static string GetStringWithNs()
{
return
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<dataset xmlns=""testNS"" xsi:schemaLocation=""Test.xsd"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<eventCommands>
<DEFINE><Event eventId=""EVENTID"" serviceId=""SERVICEID"" /></DEFINE>
</eventCommands>
</dataset>";
}
}
}
1 ответ
Если вы собираетесь запрашивать элементы, которые имеют пространства имен, используя XPath или LINQ to XML, вы должны указать это пространство имен. Например:
XNamespace ns = "testNS";
var root = XElement.Parse(xmlString);
return root.Descendants(ns + "Event")
.Where(e => (string) e.Attribute("serviceId") == "SERVICEID")
.Any();
(Я также сделал запрос чище, IMO - я склонен использовать приведение для LINQ to XML вместо использования Value
собственности, и я бы порекомендовал вам использовать Any
вместо того чтобы считать результаты.)