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 вместо того чтобы считать результаты.)

Другие вопросы по тегам