a xml file/string can be validated but yields no results if queried by XPath or linq to xml. The difference is: xmlns=""testNS"" xsi:... in the example strings. Without this xmlns=... it works and without it doesn't (but it validates).
The following programm shows the problem I don't understand: (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>";
}
}
}
If you're going to query elements that have namespaces using XPath or LINQ to XML, you have to specify that namespace. For example:
XNamespace ns = "testNS";
var root = XElement.Parse(xmlString);
return root.Descendants(ns + "Event")
.Where(e => (string) e.Attribute("serviceId") == "SERVICEID")
.Any();
(I've made the query cleaner as well, IMO - I tend to use casts for LINQ to XML rather than using the Value
property, and I'd recommend that you use Any
instead of counting the results.)
See more on this question at Stackoverflow