为啥 XmlNamespaceManager 为 HasNamespace 返回不一致的结果?
Posted
技术标签:
【中文标题】为啥 XmlNamespaceManager 为 HasNamespace 返回不一致的结果?【英文标题】:Why does XmlNamespaceManager return inconsistent results for HasNamespace?为什么 XmlNamespaceManager 为 HasNamespace 返回不一致的结果? 【发布时间】:2021-04-20 15:17:45 【问题描述】:我正在尝试处理 XML 文档并确定其中定义了哪些命名空间,但我无法从 XmlNamespaceManager.HasNamespace 获得一致的结果。在读取文档时,HasNamespace 将返回 false,即使它仍被声明并在范围内。
示例代码:
var ctx = new XmlParserContext(null, new XmlNamespaceManager(new NameTable()), null, XmlSpace.None);
var set = new XmlReaderSettings() IgnoreComments = true, IgnoreProcessingInstructions = true, IgnoreWhitespace = true ;
using (var xml = new StringReader(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<rdf:RDF " +
" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> " +
" <rdf:Description rdf:about=\"x\" /> " +
"</rdf:RDF>"))
using (var rdr = XmlReader.Create(xml, set, ctx))
rdr.MoveToContent();
Console.WriteLine(rdr.Name);
Console.WriteLine(rdr.LookupNamespace("rdf"));
Console.WriteLine(ctx.NamespaceManager.HasNamespace("rdf")); // True
rdr.Read();
Console.WriteLine(rdr.Name);
Console.WriteLine(rdr.LookupNamespace("rdf"));
Console.WriteLine(ctx.NamespaceManager.HasNamespace("rdf")); // False
rdr.Read();
Console.WriteLine(rdr.Name);
Console.WriteLine(rdr.LookupNamespace("rdf"));
Console.WriteLine(ctx.NamespaceManager.HasNamespace("rdf")); // True
Fiddle
【问题讨论】:
【参考方案1】:当阅读器输入每个新元素时,它会在命名空间管理器上调用PushScope
。一旦它离开元素(通过自闭合标签的结尾或相应的结束标签),它就会调用PopScope
。
HasNamespace
,与命名空间管理器的其他一些成员不同,只回答当前范围的问题。
获取一个值,该值指示提供的前缀是否具有为当前推送范围定义的命名空间。
(我的重点)
一般而言,您不应该过多地使用命名空间前缀,除非您实际上是在自己执行解析1,而不是利用现有工具。它是元素名称 (RDF
) 和命名空间 (http://www.w3.org/1999/02/22-rdf-syntax-ns#\
) 的组合,唯一地定义了元素的类型 - 前缀可以更改(前提是它在其有效的文档范围内始终如一地完成) ) 而不改变 XML 的信息内容。
如果你创建了这个类,你可以自己看到:
class LoggingNamespaceManager : XmlNamespaceManager
public LoggingNamespaceManager (XmlNameTable table) : base(table)
public override void PushScope()
Console.WriteLine("Push");
base.PushScope();
public override bool PopScope()
Console.WriteLine("Pop");
return base.PopScope();
并在示例的第一行实例化它而不是 XmlNamespaceManager
。
1请不要。已经有足够多的脆弱的“XML”解析器建立在关于 XML 的无效假设之上。按照您目前的做法,使用框架中提供的工具。
【讨论】:
我曾认为父级中定义的任何命名空间都会自动流向子级,但我想情况并非如此。至于前缀,很公平,但我正在使用一个定义必须可用的前缀的标准。以上是关于为啥 XmlNamespaceManager 为 HasNamespace 返回不一致的结果?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 math.inf 是浮点数,为啥我不能将其转换为整数?
为啥我的 Entity Framework Code First 代理集合为空,为啥我不能设置它?