.net 忽略 LINQ to XML 中的命名空间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1145659/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ignore namespaces in LINQ to XML
提问by Jonathan Allen
How do I have LINQ to XML iqnore all namespaces? Or alteranately, how to I strip out the namespaces?
如何让 LINQ to XML iqnore 所有命名空间?或者,如何去除命名空间?
I'm asking because the namespaces are being set in a semi-random fashion and I'm tired of having to search for nodes both with and without a namespace.
我问是因为命名空间是以半随机的方式设置的,我厌倦了搜索有和没有命名空间的节点。
回答by Pavel Minaev
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
[编辑] 为 XPath 添加解决方案
For XPath, instead of writing:
对于 XPath,而不是写:
/foo/bar | /foo/ns:bar | /ns:foo/bar | /ns:foo/ns:bar
you can use local-name()function:
您可以使用local-name()功能:
/*[local-name() = 'foo']/*[local-name() = 'bar']
回答by Ahmad Mageed
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);
回答by Jobo
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):
当我发现这个问题是为了寻找一种简单的方法来忽略属性上的命名空间时,这里有一个在访问属性时忽略命名空间的扩展,基于 Pavel 的回答(为了更容易复制,我包括了他的扩展):
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);
}

