【问题标题】:Dealing with an XSLT Namespace Mismatch处理 XSLT 命名空间不匹配
【发布时间】:2012-06-27 20:43:13
【问题描述】:

所以,希望这将是我对这个项目的最后帮助请求,因为你们已经提供了很多帮助。

基本上,我正在编写一些代码来获取 YouTube 播放列表并将其转换为 RSS 提要。我已经让它按照我想要的方式工作了,除了一个小细节:我不知道为什么,但我需要在它编译之前从 YouTube XML 中删除其中一个命名空间。

来自 YouTube 的命名空间声明如下所示:

<feed 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' gd:etag='W/&quot;A04NRn47eCp7I2A9WhJTF0g.&quot;'>

通常情况下,我会使用完全相同的,除非出于某种原因,如果我包含 xmlns='http://www.w3.org/2005/Atom' 段,则整个内容返回 null。

到目前为止,我的技术一直是从 YouTube XML 中删除该行,但这让我觉得有点不雅。如果比我了解更多的人能指出我当前的代码有什么问题,我将不胜感激。

亚当

编辑:作为参考,这是我的 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns='http://www.w3.org/2005/Atom' 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:yt='http://gdata.youtube.com/schemas/2007' gd:etag='W/&quot;Ak8EQX47eCp7I2A9WhdSEkQ.&quot;'>

<xsl:template match="/">
<xsl:for-each select="entry">
<xsl:if test="yt:position &lt; 3">
    <item>

        <title><xsl:value-of select="title" /></title>
        <xsl:variable name="videoid" select="substring-before(substring-after(media:group/media:content/@url, 'v/'), '?')" />   <!--Extracting the YouTube video ID--> 
        <description>
            <embed src="http://www.youtube.com/v/{$videoid}" type="application/x-shockwave-flash" allowscriptaccess="never" allowfullscreen="true" width="500" height="300"></embed>    <!--Embed code for the video-->
            <br />
            <br />
            <xsl:call-template name="ParseLink">    <!--Parses the video description such that URLs become links-->
                <xsl:with-param name="text" select="media:group/media:description" />   
            </xsl:call-template>
            <img src="http://i.ytimg.com/vi/{$videoid}/hqdefault.jpg" style="display:none"/>    <!--Includes hidden thumbnail-->
        </description>

        <link>http://www.youtube.com/watch?v=<xsl:value-of select="$videoid" /></link>  <!--Link to video on YouTube-->
        <guid isPermaLink="false">http://www.youtube.com/watch?v=<xsl:value-of select="$videoid" /></guid>


    </item>
</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template name="ParseLink"> <!--YouTube automatically turns URLs into links, this performs the same function for RSS-->
    <xsl:param name="text"/>
    <xsl:choose>

        <xsl:when test="contains($text,'http')">            
            <a href="http{substring-before(substring-after($text, 'http'), '&#xA;')}">Watch the complete video on our website</a>
            <br/>
            <xsl:call-template name="ParseText">    <!--Once the link is found, parses the rest of the text-->
                <xsl:with-param name="text">
                    <xsl:value-of select="substring-after($text,'&#xA;')"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:when>

        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="ParseText"> <!--Replaces line breaks in the description to <br> tags-->
    <xsl:param name="text"/>
    <xsl:choose>

        <xsl:when test="contains($text,'&#xA;')">
            <xsl:value-of select="substring-before($text,'&#xA;')"/>
            <br />
            <xsl:call-template name="ParseText">
                <xsl:with-param name="text">
                    <xsl:value-of select="substring-after($text,'&#xA;')"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:when>

        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>

    </xsl:choose>
</xsl:template>

【问题讨论】:

  • 你的 属性是什么样的?当您说“整个事情返回 null”时,您的意思是 XSLT 转换什么都不做?如果你没有命名空间匹配,你将不会匹配任何东西......
  • 我的样式表与 YouTube XML 相同,除了常规的 xmlns 标签,我有一个 xmlns:xsl 标签(我将它的确切内容添加到原始帖子中)。至于 null 的东西,我正在使用 XSLPalette 进行转换,我认为它只会在编译不正确但没有任何编码错误时显示 (null)。
  • “在编译之前”是什么意思?你在编译什么?
  • 另外,您使用什么语言来应用转换?
  • 抱歉,我使用 XSLPalette 来应用转换,所以“编译”可能不是正确的词。但基本上,您选择 XML 文档、XSLT 文档,然后单击“转换”,它会将 XSLT 转换应用于 XML 文档。

标签: xml xslt rss youtube xml-namespaces


【解决方案1】:

您的样式表不起作用的原因是您没有定义 Atom 命名空间... YouTube 的默认命名空间是 http://www.w3.org/2005/Atom。如果你想在“feed”节点上匹配,你会有一个这样的样式表:

<xsl:stylesheet xmlns:atom="http://www.w3.org/2005/Atom" ... more stuff ... >
    <xsl:template match="/atom:feed">
        etc. etc.
    </xsl:template>
</xsl:stylesheet>

编辑: 这是一个有效的示例样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"         xmlns:atom="http://www.w3.org/2005/Atom" 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:yt="http://gdata.youtube.com/schemas/2007" gd:etag="W/&quot;Ak8EQX47eCp7I2A9WhdSEkQ.&quot;">
    <xsl:template match="/atom:feed">
        <xsl:apply-templates select="atom:entry"/>
    </xsl:template>
    <xsl:template match="atom:entry">
            <p>Entry:<xsl:value-of select="atom:title"/>
            </p>
    </xsl:template>
</xsl:stylesheet>

编辑: 好的,这是您更新后的样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"         xmlns:atom="http://www.w3.org/2005/Atom" 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:yt="http://gdata.youtube.com/schemas/2007"     gd:etag="W/&quot;Ak8EQX47eCp7I2A9WhdSEkQ.&quot;">
    <xsl:template match="/atom:feed">
        <xsl:for-each select="atom:entry">
            <item>
                <title>
                <xsl:value-of select="atom:title"/>
            </title>
            <xsl:variable name="videoid" select="substring-before(substring-after(media:group/media:content/@url, 'v/'), '?')"/>
            <!--Extracting the YouTube video ID-->
            <description>
                <embed src="http://www.youtube.com/v/{$videoid}" type="application/x-shockwave-flash" allowscriptaccess="never" allowfullscreen="true" width="500" height="300"/>
                <!--Embed code for the video-->
                <br/>
                <br/>
                <xsl:call-template name="ParseLink">
                    <!--Parses the video description such that URLs become links-->
                    <xsl:with-param name="text" select="media:group/media:description"/>
                </xsl:call-template>
                <img src="http://i.ytimg.com/vi/{$videoid}/hqdefault.jpg" style="display:none"/>
                <!--Includes hidden thumbnail-->
            </description>
            <link>http://www.youtube.com/watch?v=<xsl:value-of select="$videoid"/>
            </link>
            <!--Link to video on YouTube-->
            <guid isPermaLink="false">http://www.youtube.com/watch?v=<xsl:value-of select="$videoid"/>
            </guid>
        </item>
    </xsl:for-each>
</xsl:template>
<xsl:template name="ParseLink">
    <!--YouTube automatically turns URLs into links, this performs the same function for RSS-->
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text,'http')">
            <a href="http{substring-before(substring-after($text, 'http'), '&#xA;')}">Watch the complete video on our website</a>
            <br/>
            <xsl:call-template name="ParseText">
                <!--Once the link is found, parses the rest of the text-->
                <xsl:with-param name="text">
                    <xsl:value-of select="substring-after($text,'&#xA;')"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template name="ParseText">
    <!--Replaces line breaks in the description to <br> tags-->
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text,'&#xA;')">
            <xsl:value-of select="substring-before($text,'&#xA;')"/>
            <br/>
            <xsl:call-template name="ParseText">
                <xsl:with-param name="text">
                    <xsl:value-of select="substring-after($text,'&#xA;')"/>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 不幸的是,这不起作用。无论出于何种原因,它只有在我将 atom 声明从两个文档中都删除时才会编译。
  • 如果您发布您的 XSLT,这将有很大帮助...如果可能,您可以将其缩减为基本要素。
  • 好的,添加了我的源代码。我的猜测是 标签之后的所有内容都无关紧要,但你永远不能太小心......
  • 我更新了我的答案,为您的提要提供了一个有效的 XSLT。也许您可以重构您的 XSLT 以使用类似的方法...
  • 嘿,非常感谢您对此进行调查!但是,是否需要其他步骤才能使这项工作适用于我的代码?我用你的代码替换了我的样式表和模板声明,它仍然没有编译;我需要在每个标签之前添加“atom:”吗?
猜你喜欢
  • 1970-01-01
  • 2018-03-10
  • 2011-11-08
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多