我正在用C#编写一段代码,它将接收XML并将提取一些值。当我收到的XML有一个默认命名空间时,我必须使用XmlNamespaceManager。
XmlDocument requestXml = new XmlDocument();
requestXml.LoadXml(request);
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(requestXml.NameTable);
xmlNamespaceManager.AddNamespace("ns0", requestXml.DocumentElement.NamespaceURI);
metadata.Identifier = requestXml.SelectSingleNode("//ns0:Identifier[1]", xmlNamespaceManager).InnerText;
但是当命名空间有一个前缀而不是这个代码中断时,它可以在没有命名空间管理器的情况下工作。
XmlDocument requestXml = new XmlDocument();
requestXml.LoadXml(request);
metadata.Identifier = requestXml.SelectSingleNode("//Identifier[1]").InnerText;
我希望知道xml名称空间是否有前缀是否合理?如果没有,我如何构建更健壮的代码,而不关心命名空间是否有前缀?非常感谢任何帮助。
更新
我的理解是这三者是一样的
例1:
<Node1 xmlns="myNamespace">
<Node2>
<Node3></Node3>
</Node2>
</Node1>
例2:
<ns0:Node1 xmlns:ns0="myNamespace">
<Node2>
<Node3></Node3>
</Node2>
</ns0:Node1>
示例3:
<ns0:Node1 xmlns:ns0="myNamespace">
<ns0:Node2>
<ns0:Node3></ns0:Node3>
</ns0:Node2>
</ns0:Node1>
而不是询问C#如何对待这些(我知道C#在使用默认命名空间时遇到问题),更好的问题是我要执行哪些检查以确保覆盖所有方案。
答案 0 :(得分:0)
可以假设XML中的名称空间前缀与XPath中的名称空间前缀之间存在很强的关系,但没有。
XML中节点的命名空间前缀:可以是空的,空前缀映射到当前默认的命名空间。 当前元素的默认命名空间可以是空命名空间(如果当前/父节点上没有xmlns="urn:somenamespace"
),或者如果存在xmlns
,则可以是某个特定命名空间。
样品:
<root>
<child1 xmlns="urn:ns1">
<inner xmlns="urn:reallyDeep" />
</child1>
<child2 />
<root>
空名称空间前缀映射到:
root
- 空命名空间(默认)child1
- urn:ns1
,完整节点名称可以表示为{urn:ns1}child1
child2
- 来自父(root
)inner
- urn:reallyDeep
因为它已在xmlns:
的节点上重新定义。现在XPath名称空间前缀有点简单,因为空前缀始终映射到空名称空间。
要在上面的示例中选择inner
节点,需要从3个名称空间中选择节点:空,urn:ns1
,urn:reallyDeep
。因此,名称空间管理器需要使用3个前缀构建。默认空的一个总是在那里,所以需要再添加两个。请注意,XPath中的前缀与XML中的前缀无关 - 通常的做法是匹配某些“众所周知的”命名空间(如xsi
)的前缀,但它绝对是个人选择。
p1 -> urn:ns1
p2 -> urn:reallyDeep
/root/p1:child1/p2:child2
编写代码时,除非根据XML构建XPath示例,否则显式定义映射可能是安全的,而不是尝试从XML中获取映射:
xmlNamespaceManager.AddNamespace("p1", "urn:ns1");
xmlNamespaceManager.AddNamespace("ns0", "urn:reallyDeep");
请注意,XML可以为所有命名空间使用单个命名空间前缀(空前缀或任何其他命名空间)。即以下XML在XML的观点与之前的示例相同,即使它使用前缀:
<root>
<a:child1 xmlns="urn:ns1">
<a:inner xmlns:a="urn:reallyDeep" />
</a:child1>
<child2 />
<root>
请注意,如果您不关心名称空间和前缀(在这种情况下您实际上没有正确使用XML),则可以使用local-name
XPath函数来比较名称。