如何在xmldocumentc#中处理XML中的名称空间
本文关键字:空间 XML 处理 xmldocumentc# | 更新日期: 2023-09-27 18:09:53
我有几个XML文档,它们都具有相同的结构(元素名称、属性名称和层次结构)。
然而,有些元素和属性在每个XML文档中都有自定义的名称空间,这些名称空间在设计时是不知道的。他们会改变,不要问…
在使用一组XPath遍历文档时如何处理这个问题?
我应该在处理之前删除所有的名称空间吗?
我可以自动向XmlNamespaceManager注册所有的命名空间吗?
任何想法吗?
更新:一些示例(为了清晰起见省略了命名空间声明):
<root>
<child attr="val" />
</root>
<root>
<x:child attr="val" />
</root>
<root>
<y:child z:attr="val" />
</root>
谢谢
假设您有以下xml:
<root xmlns="first">
<el1 xmlns="second">
<el2 xmlns="third">...
你可以通过以下方式编写查询来忽略命名空间:/*[local-name()='root']/*[local-name()='el1']/*[local-name()='el2']
等。当然,你可以遍历整个文档以获取名称空间并将它们加载到nsmanager中。但在一般情况下,这将导致您计算文档中的每个节点。在这种情况下,将文档视为对象树而不使用XPath会更快。
我相信你会在这个Stackoverflow线程中找到一些很好的见解
XPath + Namespace让我抓狂
在我看来,你有两种解决方案:
1-如果事先知道所有可能的名称空间集合,那么可以在开始解析之前将它们全部注册到XmlNamespaceManager中
2-使用与名称空间无关的Xpath选择器
当然,您总是可以从任何内联名称空间中清除xml文档,并在没有名称空间的干净统一的xml上开始解析。但是老实说,我不认为增加这个额外的步骤有什么好处。Scott Hanselman有一篇关于从XML文档中提取所有XML名称空间的好文章。假设,当您获得所有XML名称空间时,您可以遍历它们并在名称空间管理器中注册它们。
您可以尝试这样剥离名称空间:
//Implemented based on interface, not part of algorithm
public string RemoveAllNamespaces(string xmlDocument)
{
return RemoveAllNamespaces(XElement.Parse(xmlDocument)).ToString();
}
//Core recursion function
private XElement RemoveAllNamespaces(XElement xmlDocument)
{
if (!xmlDocument.HasElements)
{
XElement xElement = new XElement(xmlDocument.Name.LocalName);
xElement.Value = xmlDocument.Value;
return xElement;
}
return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
}
更多细节请看Peter Stegnar的回答:
如何用c#从XML中删除所有名称空间?
您还可以使用带有通配符的直接节点测试,它将匹配任何名称空间(或缺少名称空间):
$your-document/*:root/*:child/@*:attr