【问题标题】:Using LINQ to XML to Process XML in Multiple Namespaces使用 LINQ to XML 处理多个命名空间中的 XML
【发布时间】:2009-08-03 22:15:29
【问题描述】:

我正在尝试解析来自 YouTube API 的结果。我以字符串的形式正确获取结果,但无法正确解析它。

我遵循了上一个帖子的建议,但没有得到任何结果。

我的示例代码是:

string response = youtubeService.GetSearchResults(search.Term, "published", 1, 50);
XDocument xDoc = XDocument.Parse(response, LoadOptions.SetLineInfo);
var list = xDoc.Descendants("entry").ToList();
var entries = from entry in xDoc.Descendants("entry")
              select new
              {
                  Id = entry.Element("id").Value,
                  Categories = entry.Elements("category").Select(c => c.Value)
                  //Published = entry.Element("published").Value,
                  //Title = entry.Element("title").Value,
                  //AuthorName = entry.Element("author").Element("name").Value,
                  //Thumnail = entry.Element("media:group").Elements("media:thumnail").ToList().ElementAt(0)
              };
foreach (var entry in entries)
{
    // entry.Id and entry.Categories available here
}

问题是条目的计数为 0,即使 XDocument 显然具有有效值。

响应变量(Sample XML)的值可以在这里看到:http://snipt.org/lWm

(仅供参考:youtube 架构在此处列出:http://code.google.com/apis/youtube/2.0/developers_guide_protocol_understanding_video_feeds.html

谁能告诉我我在这里做错了什么?

【问题讨论】:

  • 您的第一个问题是未能发布失败 XML 的示例。我不知道你的第二个问题是什么,因为你的第一个问题。
  • 也许您的第二个问题是您没有在 foreach 循环中设置断点?您尝试过,还是依赖调试器?
  • 我会冒险猜测答案是“xml 命名空间”。你有示例 xml 吗?
  • 我用响应字符串的值更新了帖子(见这里:snipt.org/lWm)我确实设置了断点,并逐步完成了它。它完全跳过循环,条目数为 0。
  • 示例 XML 在这里:snipt.org/lWm

标签: c# xml linq-to-xml


【解决方案1】:

所有数据都在“http://www.w3.org/2005/Atom”命名空间中;你需要在整个过程中使用它:

XNamespace ns = XNamespace.Get("http://www.w3.org/2005/Atom");

...

from entry in xDoc.Descendants(ns + "entry")
select new
{
    Id = entry.Element(ns + "id").Value,
    Categories = entry.Elements(ns + "category").Select(c => c.Value)
    ...
};

等(未经测试)

【讨论】:

  • 修复了它。谢谢!就这样我明白了,为什么我需要在每个元素的名称之前添加命名空间。由于元素只是 而不是 或其他东西......我假设如果需要命名空间,我只会将它添加到 XDocument 一次。
  • 由于命名空间是继承的,所以<id>在同一个命名空间中。您需要限定任何不在默认命名空间中的内容。
  • 我需要的元素之一被命名为: ...当我使用 entry.Element(ns + "media:group") 时出现错误。有没有特定的方法可以访问这个元素?
  • media 是不同命名空间的别名;使用var media = XNamespace.Get("search.yahoo.com/mrss/");,然后使用entry.Elements(media + "group")
  • 使用 XNamespace.Get("namespace.com/") 和只声明 XNamespace 类型的字符串有什么区别,比如 XNamespace ns = "namespace.com"?
【解决方案2】:

当您看到prefix:name 时,表示name 在其前缀已声明为prefix 的命名空间中。如果您查看文档顶部,您将看到xmlns:media=somethingsomething 是用于前缀为 media 的任何内容的命名空间。

这意味着您需要为每个需要引用的命名空间创建一个 XNamespace:

XNamespace media = XNamespace.Get("http://search.yahoo.com/mrss/");

然后使用media 作为该命名空间中的名称:

media + "group"

本文档中的命名空间是:

 xmlns="http://www.w3.org/2005/Atom" 
 xmlns:app="http://www.w3.org/2007/app" 
 xmlns:media="http://search.yahoo.com/mrss/" 
 xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" 
 xmlns:gd="http://schemas.google.com/g/2005" 
 xmlns:gml="http://www.opengis.net/gml" 
 xmlns:yt="http://gdata.youtube.com/schemas/2007" 
 xmlns:georss="http://www.georss.org/georss"

【讨论】:

    【解决方案3】:

    你需要设置命名空间。

    在命名空间中创建 XName
    与 XML 一样,XName 可以在命名空间中,也可以不在命名空间中。
    对于 C#,在命名空间中创建 XName 的推荐方法是声明 XNamespace 对象,然后使用加法运算符的覆盖。

    http://msdn.microsoft.com/en-us/library/system.xml.linq.xname.aspx

    【讨论】:

      猜你喜欢
      • 2014-02-07
      • 2011-01-21
      • 2012-07-01
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多