【问题标题】:How do I get a NameTable from an XDocument?如何从 XDocument 中获取 NameTable?
【发布时间】:2026-02-09 09:25:01
【问题描述】:

如何从 XDocument 中获取 NameTable?

它似乎没有 XmlDocument 所具有的 NameTable 属性。

编辑:从缺乏答案来看,我猜我可能错过了重点。

我正在对这样的 XDocument 进行 XPath 查询...

document.XPathSelectElements("//xx:Name", namespaceManager);

它工作正常,但我必须手动将我想使用的命名空间添加到 XmlNamespaceManager,而不是像使用 XmlDocument 那样从 XDocument 中检索现有的名称表。

【问题讨论】:

标签: c# xml xpath linq-to-xml


【解决方案1】:

您需要通过 XmlReader 推送 XML 并使用 XmlReader 的 NameTable 属性。

如果您已经将 Xml 加载到 XDocument 中,请确保使用 XmlReader 加载 XDocument:-

XmlReader reader = new XmlTextReader(someStream);
XDocument doc = XDocument.Load(reader);
XmlNameTable table = reader.NameTable;

如果您使用 XDocument 从头开始​​构建 Xml,您将需要调用 XDocument 的 CreateReader 方法,然后让阅读器消耗一些东西。一旦使用了阅读器(比如加载另一个 XDocument,但最好是一些什么都不做的接收器,这只会导致阅读器遍历 XDocument 的内容),您可以检索 NameTable。

【讨论】:

    【解决方案2】:

    我是这样做的:

    //Get the data into the XDoc
    XDocument doc = XDocument.Parse(data);
    //Grab the reader
    var reader = doc.CreateReader();
    //Set the root
    var root = doc.Root;
    //Use the reader NameTable
    var namespaceManager = new XmlNamespaceManager(reader.NameTable);
    //Add the GeoRSS NS
    namespaceManager.AddNamespace("georss", "http://www.georss.org/georss");  
    //Do something with it
    Debug.WriteLine(root.XPathSelectElement("//georss:point", namespaceManager).Value);  
    

    马特

    【讨论】:

    • 如果您只有 xml 文本或 XDocument,这是唯一的方法,但如果您有 XmlReader,则以前的解决方案更有效。
    【解决方案3】:

    我必须手动将要使用的命名空间添加到 XmlNamespaceManager 而不是从中检索现有的名称表 XDocument 就像使用 XmlDocument 一样。

    XDocument project = XDocument.Load(path);
    //Or: XDocument project = XDocument.Parse(xml);
    var nsMgr = new XmlNamespaceManager(new NameTable());
    //Or: var nsMgr = new XmlNamespaceManager(doc.CreateReader().NameTable);
    nsMgr.AddNamespace("msproj", "http://schemas.microsoft.com/developer/msbuild/2003");
    var itemGroups = project.XPathSelectElements(@"msproj:Project/msproj:ItemGroup", nsMgr).ToList();
    

    【讨论】:

    • 即FWIW,只是为了澄清一下,XmlNameSpaceManager 在使用 System.Xml.Xpath 扩展时似乎可以使用 any NameTable (甚至是一个新的、空的) - 它不必与XDocument,这个工作的另一个例子here
    【解决方案4】:

    也可以通过 XPathNavigator 来完成。当您既不知道 Xml 文件编码也不知道命名空间前缀时会很有用。

    XDocument xdoc = XDocument.Load(sourceFileName);
    XPathNavigator navi = xdoc.Root.CreateNavigator();
    XmlNamespaceManager xmlNSM = new XmlNamespaceManager(navi.NameTable);
    //Get all the namespaces from navigator
    IDictionary<string, string> dict = navi.GetNamespacesInScope(XmlNamespaceScope.All);
    //Copy them into Manager
    foreach (KeyValuePair<string, string> pair in dict)
    {
        xmlNSM.AddNamespace(pair.Key, pair.Value);
    }
    

    【讨论】: