【问题标题】:Getting the right node in Linq to XML在 Linq to XML 中获取正确的节点
【发布时间】:2012-07-11 12:09:38
【问题描述】:

我正在尝试解析包含某个频道上所有上传视频的 XML 文件。我试图在 <media:content> 节点之一中获取 URL 属性的值并将其放入 ViewerLocation 字段中。但是有几个。我目前的代码是这样的:

var videos = from xElem in xml.Descendants(atomNS + "entry")
select new YouTubeVideo()
{
    Title = xElem.Element(atomNS + "title").Value,
    Description = xElem.Element(atomNS + "content").Value,
    DateUploaded = xElem.Element(atomNS + "published").Value,
    ThumbnailLocation = xElem.Element(mediaNS + "group").Element(mediaNS + "content").Attribute("url").Value,
    ViewerLocation = xElem.Element(mediaNS + "group").Element(mediaNS + "content").Attribute("url").Value
};

它让我得到了 XML 中的第一个节点,用于输入名称为 <media:content> 的条目,正如您所期望的那样。但是,XML 中的第一个条目不是我想要的。我想要第二个。

下面是相关的 XML。

<!-- I currently get the value held in this node -->
<media:content 
  url='http://www.youtube.com/v/ZTUVgYoeN_b?f=gdata_standard...'
  type='application/x-shockwave-flash' medium='video'
  isDefault='true' expression='full' duration='215' yt:format='5'/>

<!-- What i actually want is this one -->
<media:content
  url='rtsp://rtsp2.youtube.com/ChoLENy73bIAEQ1kgGDA==/0/0/0/video.3gp'
  type='video/3gpp' medium='video'
  expression='full' duration='215' yt:format='1'/>

<media:content
  url='rtsp://rtsp2.youtube.com/ChoLENy73bIDRQ1kgGDA==/0/0/0/video.3gp'
  type='video/3gpp' medium='video'
  expression='full' duration='215' yt:format='6'/>

我想要第二个节点,因为它的类型为“video/3gpp”。我将如何选择那个?我的逻辑是

如果属性(type == "video/3gpp") 得到这个值。

但我不知道如何在 Linq 中表达。

谢谢,

丹尼。

【问题讨论】:

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


    【解决方案1】:

    大概是这样的;

    where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
    

    编辑:如果不假设 OP 不了解 Linq,我不太知道如何扩展和解释这一点。您想进行原始查询;

    from xElem in xml.Descendants(atomNS + "entry") 
    where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
    select new YouTubeVideo() { 
      ...
    }
    

    您可以查询节点的属性,就像您可以查看文档的元素一样。如果有多个具有该属性的元素,那么您可以(假设您总是想要找到的第一个)..

      ( from xElem in xml.Descendants(atomNS + "entry") 
        where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
        select new YouTubeVideo() { 
          ...
        }).First();
    

    我更改了原始帖子,因为我相信您要查询的节点是 Element(atomNS + "content"),而不是顶级 xElem

    【讨论】:

    • 抱歉,一开始我不确定如何扩展。但它有所帮助,因为我认为我最初犯了错误而被问到。
    • 现在添加 where 原因意味着没有任何内容返回到 var 中:/
    • 您在帖子中提到它让您获得了第一个条目,这是否意味着您只获得了第一个元素,而不是全部三个?如果是这样的话,这就是为什么你现在什么都得不到,因为你已经丢弃了那个结果。
    • 基本上就在这一点 linq 之后,我将 AddRange() 放入列表中。该列表曾经填充有 Title、Description、DateUploaded、ThumbnailLocation、ViewerLocation 的项目。但是 ViewerLocation 没有我想要的。现在列表是空的,根本不包含任何 Youtube 视频对象。
    【解决方案2】:

    使用来自 Xml Library 的 XPath(只是因为我知道如何使用它)和相关的 Get 方法:

    string videoType = "video/3gpp";
    
    XElement root = XElement.Load(file); // or .Parse(xmlstring)
    var videos = root.XPath("//entry")
        .Select(xElem => new YouTubeVideo()
        {
            Title = xElem.Get("title", "title"),
            Description = xElem.Get("content", "content"),
            DateUploaded = xElem.Get("published", "published"),
            ThumbnailLocation = xElem.XGetElement("group/content[@type={0}]/url", "url", videoType),
            ViewerLocation = xElem.XGetElement("group/content[@type={0}]/url", "url", videoType)
        });
    

    如果视频类型没有改变,您可以将 XGetElement 替换为:

    xElem.XGetElement("group/content[@type='video/3gpp']/url", "url")
    

    不必使用库指定命名空间,这样会更干净。您可以查看 Microsoft 的 XPathSelectElements()XPathSelectElement(),但它们要求您指定命名空间并且没有很好的 Get 方法 imo。需要注意的是,该库不是完整的 XPath 实现,但它确实适用于上述内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      • 1970-01-01
      • 2016-06-10
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多