C# 为什么XmlNamespaceManager为HasNamespace返回不一致的结果?
我试图处理一个XML文档并确定其中定义了哪些名称空间,但从XmlNamespaceManager.HasNamespace获得一致的结果时遇到了问题。当它读取文档时,HasNamespace将返回false,即使它仍然声明并在范围内 示例代码:C# 为什么XmlNamespaceManager为HasNamespace返回不一致的结果?,c#,xml,xmlreader,C#,Xml,Xmlreader,我试图处理一个XML文档并确定其中定义了哪些名称空间,但从XmlNamespaceManager.HasNamespace获得一致的结果时遇到了问题。当它读取文档时,HasNamespace将返回false,即使它仍然声明并在范围内 示例代码: var ctx = new XmlParserContext(null, new XmlNamespaceManager(new NameTable()), null, XmlSpace.None); var set = new XmlR
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
}
var ctx=new-XmlParserContext(null,new-XmlNamespaceManager(new-NameTable()),null,XmlSpace.None);
var set=new XmlReaderSettings(){IgnoreComments=true,IgnoreProcessingInstructions=true,IgnoreWhitespace=true};
使用(var xml=newstringreader)(
"" +
" " +
" " +
""))
使用(var rdr=XmlReader.Create(xml,set,ctx))
{
rdr.MoveToContent();
Console.WriteLine(rdr.Name);
WriteLine(rdr.LookupNamespace(“rdf”));
Console.WriteLine(ctx.NamespaceManager.HasNamespace(“rdf”);//True
rdr.Read();
Console.WriteLine(rdr.Name);
WriteLine(rdr.LookupNamespace(“rdf”));
Console.WriteLine(ctx.NamespaceManager.HasNamespace(“rdf”);//False
rdr.Read();
Console.WriteLine(rdr.Name);
WriteLine(rdr.LookupNamespace(“rdf”));
Console.WriteLine(ctx.NamespaceManager.HasNamespace(“rdf”);//True
}
当读者输入每个新元素时,它将调用命名空间管理器上的
PushScope
。一旦它离开元素(通过自动关闭标记或相应的结束标记的结尾),它将调用PopScope
与命名空间管理器的某些其他成员不同,它只回答当前范围的问题
获取一个值,该值指示提供的前缀是否具有为当前推式作用域定义的命名空间
(我的重点)
一般来说,您不应该过多地使用名称空间前缀,除非您实际上是在解析自己,而不是利用现有的工具。它是元素名(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
但请不要这样做。已经有足够多的脆弱的“XML”解析器建立在关于XML的无效假设之上。使用框架中提供的工具,就像您目前所做的那样。我原以为父级中定义的任何名称空间都会自动流到子级,但我想情况并非如此。至于前缀,这很公平,但我正在使用一个标准来定义必须可用的前缀。