如何使用C#(XNamespace / XElement)导航XML文档

时间:2013-11-25 23:57:23

标签: c# xml linq youtube namespaces

我无法在检索YouTube数据Feed的C#Windows Phone 8应用程序中提取所需元素。 XML文档如下所示。它来自YouTube播放列表供稿:

<entry gd:etag="W/&quot;YDwqeyM.&quot;" xmlns:gd="http://schemas.google.com/g/2005" xmlns="http://www.w3.org/2005/Atom">
  <media:group xmlns:media="http://search.yahoo.com/mrss/">
    <media:category label="Science &amp; Technology" scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Tech</media:category>
    <media:content url="https://www.youtube.com/v/vt7PLhQKYlU?version=3&amp;f=playlists&amp;app=youtube_gdata" type="application/x-shockwave-flash" medium="video" isDefault="true" expression="full" duration="1668" yt:format="5" xmlns:yt="http://gdata.youtube.com/schemas/2007" />
    <media:content url="rtsp://r5---sn-p5qlsu7d.c.youtube.com/CiULENy73wIaHAlVYgoULs_evhMYDSANFEgGUglwbGF5bGlzdHMM/0/0/0/video.3gp" type="video/3gpp" medium="video" expression="full" duration="1668" yt:format="1" xmlns:yt="http://gdata.youtube.com/schemas/2007" />
    <media:content url="rtsp://r5---sn-p5qlsu7d.c.youtube.com/CiULENy73wIaHAlVYgoULs_evhMYESARFEgGUglwbGF5bGlzdHMM/0/0/0/video.3gp" type="video/3gpp" medium="video" expression="full" duration="1668" yt:format="6" xmlns:yt="http://gdata.youtube.com/schemas/2007" />
    <media:credit role="uploader" scheme="urn:youtube" yt:display="TheDigitalDigest" yt:type="partner" xmlns:yt="http://gdata.youtube.com/schemas/2007">thedigitaldigest</media:credit>
    <media:description type="plain">Surface 2</media:description>
    <yt:videoid xmlns:yt="http://gdata.youtube.com/schemas/2007">vt7PLhQKYlU</yt:videoid>
  </media:group>
</entry>

我需要修改下面的代码,使用 XNamespace / XElement 方法解析条目,以查找 yt:video 元素而不是 id 元素。我可以找到没有前缀的命名空间元素(不包含冒号)。这是我需要修改的代码:

public YouTubeVideo(XNamespace atomns, XElement entry, XNamespace medians)
    {
        var id = entry.Element(atomns.GetName("id")) != null && entry.Element(atomns.GetName("id")).Value != null
            ? entry.Element(atomns.GetName("id")).Value.Split(':').Last()
            : string.Empty;
        VideoUrl = "http://gdata.youtube.com/feeds/api/videos/" + id;
    }

注意,我发现这个SO帖子谈论了名称空间:

Using LINQ to XML to Process XML in Multiple Namespaces

我担心的是,可能有一种方法可以从XML中提取 yt:videoid 而无需将 yt 命名空间硬编码到代码中,因为 yt 名称空间位于 yt:videoid 元素内,作为 xmlns 属性。是否有一种方法可以选择具有命名空间引用作为属性的命名空间节点?如果没有,从一个带有它作为属性的元素中选择命名空间的正确方法是什么,以及访问命名空间元素的内容是什么?

更新:为了解决当前的问题,我使用下面的代码。我仍然想知道一个不忽略名称空间的解决方案,如下面的代码:

string videoid = (from child in entry.Descendants()
                      where child.Name.LocalName == "videoid"
                      select child.Value).FirstOrDefault();

更新:我现在有一个XPath样式查询,它不会忽略有效的命名空间,但它似乎有点冗长,我希望有人建议一个更精简的方法,如果有的话。我知道我可以添加三元运算符,但我想知道是否有一种方法来组合命名空间分辨率和元素选择?:

        // Get the namespaces for the "media" group, since it contains the "yt" group,
        //  and for the "yt" group itself.
        XNamespace xnsMediaGroup = entry.GetNamespaceOfPrefix("media");
        XNamespace xnsYouTube = entry.GetNamespaceOfPrefix("yt");

        // Got valid namespace references?
        if ((xnsMediaGroup != null) && (xnsYouTube != null))
        {
            // Yes.  Select the media group element.
            XElement xelemMediaGroup = entry.Element(xnsMediaGroup.GetName("group"));

            if (xelemMediaGroup != null)
            {
                // Select the YouTube videoid element.
                XElement xelemYTVideoId = xelemMediaGroup.Element(xnsYouTube.GetName("videoid"));

                if (xelemYTVideoId != null)
                    // Return the video's ID.
                    videoid = xelemYTVideoId.Value;
            }
        }

1 个答案:

答案 0 :(得分:1)

我认为你应该阅读Scott Hanselman的文章:Get namespaces from an XML Document with XPathDocument and LINQ to XML