在Linq中获取正确的节点到XML

时间:2012-07-11 12:09:39

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

我正在尝试解析包含特定频道上所有上传视频的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'。我该如何选择那个呢?我的逻辑是

if attribute(type ==“video / 3gpp”)获取此值。

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

谢谢,

丹尼。

2 个答案:

答案 0 :(得分:0)

可能类似;

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();

我更改了原帖,因为我相信您查询的节点是元素(atomNS +“内容”),而不是顶级xElem

答案 1 :(得分:0)

使用来自此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实现,但它确实适用于上述。