0

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

1 Answers1

0

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.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194