Ignore namespaces in LINQ to XML Ignore namespaces in LINQ to XML xml xml

Ignore namespaces in LINQ to XML


Instead of writing:

nodes.Elements("Foo")

write:

nodes.Elements().Where(e => e.Name.LocalName == "Foo")

and when you get tired of it, make your own extension method:

public static IEnumerable<XElement> ElementsAnyNS<T>(this IEnumerable<T> source, string localName)    where T : XContainer{    return source.Elements().Where(e => e.Name.LocalName == localName);}

Ditto for attributes, if you have to deal with namespaced attributes often (which is relatively rare).

[EDIT] Adding solution for XPath

For XPath, instead of writing:

/foo/bar | /foo/ns:bar | /ns:foo/bar | /ns:foo/ns:bar

you can use local-name() function:

/*[local-name() = 'foo']/*[local-name() = 'bar']


Here's a method to strip namespaces:

private static XElement StripNamespaces(XElement rootElement){    foreach (var element in rootElement.DescendantsAndSelf())    {        // update element name if a namespace is available        if (element.Name.Namespace != XNamespace.None)        {            element.Name = XNamespace.None.GetName(element.Name.LocalName);        }        // check if the element contains attributes with defined namespaces (ignore xml and empty namespaces)        bool hasDefinedNamespaces = element.Attributes().Any(attribute => attribute.IsNamespaceDeclaration ||                (attribute.Name.Namespace != XNamespace.None && attribute.Name.Namespace != XNamespace.Xml));        if (hasDefinedNamespaces)        {            // ignore attributes with a namespace declaration            // strip namespace from attributes with defined namespaces, ignore xml / empty namespaces            // xml namespace is ignored to retain the space preserve attribute            var attributes = element.Attributes()                                    .Where(attribute => !attribute.IsNamespaceDeclaration)                                    .Select(attribute =>                                        (attribute.Name.Namespace != XNamespace.None && attribute.Name.Namespace != XNamespace.Xml) ?                                            new XAttribute(XNamespace.None.GetName(attribute.Name.LocalName), attribute.Value) :                                            attribute                                    );            // replace with attributes result            element.ReplaceAttributes(attributes);        }    }    return rootElement;}

Example usage:

XNamespace ns = "http://schemas.domain.com/orders";XElement xml =    new XElement(ns + "order",        new XElement(ns + "customer", "Foo", new XAttribute("hello", "world")),        new XElement("purchases",            new XElement(ns + "purchase", "Unicycle", new XAttribute("price", "100.00")),            new XElement("purchase", "Bicycle"),            new XElement(ns + "purchase", "Tricycle",                new XAttribute("price", "300.00"),                new XAttribute(XNamespace.Xml.GetName("space"), "preserve")            )        )    );Console.WriteLine(xml.Element("customer") == null);Console.WriteLine(xml);StripNamespaces(xml);Console.WriteLine(xml);Console.WriteLine(xml.Element("customer").Attribute("hello").Value);


As I found this question in search for an easy way to ignore namespaces on attributes, here's an extension for ignoring namespaces when accessing an attribute, based on PavelĀ“s answer (for easier copying, I included his extension):

public static XAttribute AttributeAnyNS<T>(this T source, string localName)where T : XElement{    return source.Attributes().SingleOrDefault(e => e.Name.LocalName == localName);}public static IEnumerable<XElement> ElementsAnyNS<T>(this IEnumerable<T> source, string localName)where T : XContainer{    return source.Elements().Where(e => e.Name.LocalName == localName);}