Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

xml - xsl scenario when a node is not present in every for each loop

I have an xml represented by this http://feeds.contenthub.aol.com/syndication/2.0/feed/53dfbe8362619. I am also postin a patch of an xml

<item>
<title>
<![CDATA[ Jon Lester Uses Full-Page Ad To Thank Red Sox Fans ]]>
</title>
<description type="html">
<![CDATA[
<p>Jon Lester made a classy move by taking a full-age ad in the Sunday edition of the Boston Globe...</p>
]]>
</description>
<link>
http://www.huffingtonpost.com/2014/08/03/jon-lester-full-page-ad-red-sox-fans_n_5645882.html
</link>
<source_id>qkjDte</source_id>
<guid isPermalink="false">0d85d061e4436ffaeeeafa9a86c3a253</guid>
<dc:creator>Michael Klopman</dc:creator>
<dc:publisher>Huff. Post: United States - Sports</dc:publisher>
<dc:rightsHolder>Huff. Post: United States - Sports</dc:rightsHolder>
<pubDate>Sun, 03 Aug 2014 19:58:04 +0000</pubDate>
<ingested>1407096147696297537</ingested>
<modified>2014-08-05 14:58:17</modified>
<category>
<![CDATA[ Jon Lester full page ad ]]>
</category>
<category>
<![CDATA[ brew-pub ]]>
</category>
<category>
<![CDATA[ Red Sox Jon Lester ]]>
</category>
<category>
<![CDATA[ mlb ]]>
</category>
<category>
<![CDATA[ major league baseball ]]>
</category>
<category>
<![CDATA[ Jon LEster full-page ad ]]>
</category>
<category>
<![CDATA[ Jon Lester Boston Globe ]]>
</category>
<category>
<![CDATA[ Oakland A's ]]>
</category>
<category>
<![CDATA[ Red Sox ]]>
</category>
<category>
<![CDATA[ oakland Athletics ]]>
</category>
<category>
<![CDATA[ Boston Red Sox ]]>
</category>
<media:content url="http://i.huffpost.com/gen/1945400/original.jpg" width="" height="" medium="image">
<media:keywords>headline</media:keywords>
<media:media_html>
<![CDATA[ <HH--PHOTO--JON-LESTER--1945400--HH> ]]>
</media:media_html>
<dc:identifier>
<![CDATA[ ]]>
</dc:identifier>
<media:credit>
<![CDATA[ ASSOCIATED PRESS ]]>
</media:credit>
<media:description>
<![CDATA[
Boston Red Sox starting pitcher Jon Lester heads to the bull pen before a baseball game against the Kansas City Royals in Boston, Sunday, July 20, 2014. (AP Photo/Michael Dwyer)
]]>
</media:description>
<media:title>
<![CDATA[ ]]>
</media:title>
</media:content>
</item>
<item>
<title>
<![CDATA[ 10 Home Runs of the Century ]]>
</title>
<description type="html">
<![CDATA[ %Slideshow-209585% ]]>
</description>
<link>
http://www.mandatory.com/2014/07/24/10-home-runs-of-the-century/
</link>
<source_id>blEPZi</source_id>
<guid isPermalink="false">20936381</guid>
<dc:creator>Joshua Crouthamel</dc:creator>
<dc:publisher>Mandatory</dc:publisher>
<dc:rightsHolder>Mandatory</dc:rightsHolder>
<pubDate>Thu, 24 Jul 2014 15:52:00 +0000</pubDate>
<ingested>1406220498372620179</ingested>
<modified>2014-07-24 16:45:40</modified>
<category>
<![CDATA[ co-gallery ]]>
</category>
<category>
<![CDATA[ Sports ]]>
</category>
<ss:slideshow>
<ss:media_html>
<![CDATA[ %slideshow-209585% ]]>
</ss:media_html>
<media:title>
<![CDATA[ 10 Home Runs of the Century ]]>
</media:title>
<dc:identifier>
<![CDATA[ 209585 ]]>
</dc:identifier>
<dc:created>2014-07-24 15:52:00</dc:created>
<media:content url="http://www.blogcdn.com/slideshows/images/slides/279/483/8/S2794838/slug/l/1-2.jpg" width="" height="" medium="image">
<dc:identifier>
<![CDATA[ 2794838 ]]>
</dc:identifier>
<media:credit>
<![CDATA[ New York Giants ]]>
</media:credit>
<media:description>
<![CDATA[
<p>The home run is the best part of baseball. But not all home runs are created equal. Here are the 10 most amazing home runs of the century. (Prepare to argue in the comments.)</p> <p><strong>Bobby Thomson&rsquo;s &ldquo;Shot Heard &lsquo;Round the World&rdquo;</strong><br /> <strong>October 3, 1951:</strong> Things weren&rsquo;t looking good for the New York Giants coming into the ninth inning of the National League pennant game &mdash; they were down 4-1 to the Brooklyn Dodgers, and the game&rsquo;s winner would take home the title. Enter Bobby Thomson, who hit a game-ending three-run homer &hellip; and the New York Polo Grounds went wild.&nbsp;</p>
]]>
</media:description>
<media:title>
<![CDATA[ Bobby Thomson’s “Shot Heard ‘Round the World” ]]>
</media:title>
</media:content>
<media:content url="http://www.blogcdn.com/slideshows/images/slides/279/484/0/S2794840/slug/l/2-2.jpg" width="" height="" medium="image">
<dc:identifier>
<![CDATA[ 2794840 ]]>
</dc:identifier>
<media:credit>
<![CDATA[ Los Angeles Dodgers ]]>
</media:credit>
<media:description>
<![CDATA[
<p><strong>Kirk Gibson&rsquo;s World Series Home Run</strong><br /> <strong>October 15, 1988:</strong> Talk about an incredible underdog story. Gibson was nursing two knee injuries as well as a virus when he was called in to pinch hit for the Los Angeles Dodgers at the bottom of the ninth, Dodgers down by one with two outs on the board. His two-run, walk-off homer, followed by subsequent fist-pumping round of the bases, was one of the greatest moments in LA sporting history (and won the game).</p>
]]>

So my xsl is iterating over every item node to get <title>, <description>, <media:content/@url> and <link> node. However there are 2 corner cases which I want to address in my xslt. If you look at the feed Link http://feeds.contenthub.aol.com/syndication/2.0/feed/53dfbe8362619 within the node which I am for:eaching through there are scenarion when the node is not present and hence I cannot access it @url attribute. So when /@url attribute is not present there are nodes those are also not there for every node but they are for those where node is not present. I want to write an xsl which does this

if(!media:content node) { get ss:slideshow/media:content[1]/@url//first media:content node and its url attribute }

second cornercase is some node have %slideshow. I want to get ss:slideshow/media:description if the normal node contains '%slideshow' as content. I have written xsl for that but it does not give me the media:description within ss:slideshow. so what I want is something like this if(description node containe '%Slideshow) { use ss;slideshow/media:description } It breaks with a failed XSL transformation when I try to access the ss:slideshow node.

My XSL is as follows

 <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:media="http://search.yahoo.com/mrss/">
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="/">
            <rss xmlns:georss="http://www.georss.org/georss" xmlns:twitter="http://api.twitter.com" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
                <channel>
                    <author>
                        <xsl:text>Content-Feed-Pics</xsl:text>
                    </author>
                    <xsl:for-each select="rss/channel/item[position() &lt; 30]">
                        <item>
                            <title><xsl:value-of select="title"/></title>
                            <xsl:call-template name="deleteEllipses">
                                <xsl:with-param name="nodeData" select="description"></xsl:with-param>
                            </xsl:call-template>
                            <!--author><xsl:value-of select="dc:rss/dc:channel/dc:item/dc:creator"/></author-->
                           <!--icon>
                           <xsl:value-of select="concat(entities/media//media_url,':thumb')"/>                    
                           </icon-->


                            <link><xsl:value-of select="link"/></link>
                                           <!--description><xsl:value-of select="media:content[1]/media:description"/></description-->

                   <!--xsl:variable name="descriptionVar"><xsl:value-of select="description"/></xsl:variable-->

                            <!--description><xsl:value-of select="description"/></description-->
                            <enclosure>
                     <xsl:attribute name="url">
                    <!-- <xsl:value-of select="."/>
                    <xsl:value-of select="concat('myText:', /*/properties/property[@name='report']/@value)" /> -->
                       <xsl:value-of select="media:content/@url"/>                         
                   </xsl:attribute>
                             <xsl:attribute name="type">
                              <xsl:text>image/jpg</xsl:text>
                              </xsl:attribute>
                          </enclosure>
                            <!--pubDate><xsl:value-of select="pubDate"/></pubDate-->
                        </item>
                    </xsl:for-each>
                </channel>
            </rss>
        </xsl:template>
         <xsl:template name="deleteEllipses">
            <xsl:param name="nodeData"/>
            <xsl:choose>
                <xsl:when test="contains($nodeData, '%Slideshow')">
                    <!--xsl:variable name="prestring" select="substring-before($nodeData, 'Read more')"/-->
                    <!--xsl:variable name="poststring" select="substring-after($nodeData, '...')"/>
                    <xsl:variable name="poststringspace" select="concat(' ', $poststring)"/-->
                    <description><xsl:value-of select="//media:content[1]/media:description"/></description>
                </xsl:when>
                <xsl:otherwise>
                    <description><xsl:value-of select="$nodeData"/></description>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

    </xsl:stylesheet>

Please help me with this.

Regards Swaraj?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, what you need to do is declare the relevant namespace in your XSLT, to allow to easily access nodes in the XML belonging to that namespace

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:media="http://search.yahoo.com/mrss/"
    xmlns:ss="http://contenthub.aol.com/slideshow/">

Then, one solution is to just use an xsl:choose to determine whether a media:content element is present.

<xsl:attribute name="url">
  <xsl:choose>
   <xsl:when test="media:content">
       <xsl:value-of select="media:content/@url"/>                         
   </xsl:when>
   <xsl:otherwise>
       <xsl:value-of select="ss:slideshow/media:content[1]/@url"/>                         
   </xsl:otherwise>
  </xsl:choose>
</xsl:attribute>

In fact, as it looks like you are still looking for a media:content element, but just at a different level, you can getaway with not having an xsl:choose at all, and just do this...

<xsl:attribute name="url">
   <xsl:value-of select=".//media:content/@url"/>  
</xsl:attribute>

Better still, use "Attribute Value Templates" to create the attributes on the enclosure item directly

<enclosure url="{.//media:content/@url}" type="image/jpg" />

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...