【问题标题】:XPath with XmlDocument not finding nodes带有 XmlDocument 的 XPath 找不到节点
【发布时间】:2016-11-14 01:14:44
【问题描述】:

所以我的 XPath 没有从 XML 树中选择任何节点时遇到了一些问题。到目前为止,这是我的代码:

var reader = new XmlDocument();
reader.Load(@"http://www.fieldgulls.com/rss/current");

XmlNodeList list = reader.SelectNodes("./entry");

我还尝试过 */entry、//entry 等的 XPath 值。我似乎无法得到任何工作。我做错了什么?

【问题讨论】:

  • 您的 XML 节点可能位于命名空间中,但如果没有 minimal reproducible example,我们无法确定。你能edit你的问题包括XML吗?或者查看Using Xpath With Default Namespace in C# 以获得有关如何选择具有命名空间的节点的一般答案。
  • 哦 - "http://www.fieldgulls.com/rss/current" 是实际的实时 URL。在这种情况下,<Entry> 节点的正确命名空间是 xmlns="http://www.w3.org/2005/Atom"

标签: c# xml xpath xmldocument


【解决方案1】:

问题在于元素<Entry>实际上是在根节点的默认命名空间中,即"http://www.fieldgulls.com/rss/current"

<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"> <!--The default namespace for nested elements is set here with the xmlns= attribute -->
  <title>Field Gulls -  All Posts</title>
  <subtitle>The stupidest name in smart football analysis.</subtitle>
  <icon>https://cdn3.vox-cdn.com/community_logos/50215/fieldgulls-fav.png</icon>
  <updated>2016-11-13T17:00:02-08:00</updated>
  <id>http://www.fieldgulls.com/rss/current/</id>
  <link type="text/html" href="http://www.fieldgulls.com/" rel="alternate"/>
  <entry>
    <!--Remainder commented out-->

因此您需要使用适当的命名空间和适当的SelectNodes() 覆盖来选择节点:

var reader = new XmlDocument();
reader.Load(@"http://www.fieldgulls.com/rss/current");

var nsmgr = new XmlNamespaceManager(reader.NameTable);
nsmgr.AddNamespace("a", "http://www.w3.org/2005/Atom");

XmlNodeList list = reader.SelectNodes(".//a:entry", nsmgr);

在这种情况下,我发现使用以下基于较新的LINQ to XML 类库的调试实用程序来使每个节点的命名空间明显:

public static class XObjectExtensions
{
    public static IEnumerable<string> DumpXmlElementNames(this XDocument doc)
    {
        return doc.Root.DumpXmlElementNames();
    }

    public static IEnumerable<string> DumpXmlElementNames(this XElement root)
    {
        if (root == null)
            return Enumerable.Empty<string>();
        var startCount = root.AncestorsAndSelf().Count();
        return root.DescendantsAndSelf().Select(el => string.Format("{0}\"{1}\"",
            new string(' ', 2 * (el.AncestorsAndSelf().Count() - startCount)), el.Name.ToString()));
    }
}

那么,在调试的时候,你会这样做:

Console.WriteLine("Dumping a list of all element names and namespaces: ");
Console.WriteLine(String.Join("\n", XDocument.Load(@"http://www.fieldgulls.com/rss/current").DumpXmlElementNames()));

产生以以下开头的输出:

"{http://www.w3.org/2005/Atom}feed"
  "{http://www.w3.org/2005/Atom}title"
  "{http://www.w3.org/2005/Atom}subtitle"
  "{http://www.w3.org/2005/Atom}icon"
  "{http://www.w3.org/2005/Atom}updated"
  "{http://www.w3.org/2005/Atom}id"
  "{http://www.w3.org/2005/Atom}link"
  "{http://www.w3.org/2005/Atom}entry"

示例fiddle

【讨论】:

    【解决方案2】:

    尝试使用SyndicationFeed 类。使用 RSS 很容易。

    using (var xmlReader = XmlReader.Create(@"http://www.fieldgulls.com/rss/current"))
    {
        var feed = SyndicationFeed.Load(xmlReader);
    
        foreach (var item in feed.Items)
        {
            // use item.Title.Text and so on
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-03-01
      • 2012-11-10
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多