home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / WindowsServerTrial / server.iso / sources / install.wim / 2 / Windows / System32 / msfeeds.dll / HTML / ATOM1NORMALIZER.XSL < prev    next >
Text File  |  2008-01-19  |  21KB  |  409 lines

  1. <xsl:stylesheet version="1.0" 
  2.   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  3.   xmlns:atom="http://www.w3.org/2005/Atom"
  4.   xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005"
  5.   xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  6.   xmlns:msfeednorm="urn:microsoft:feed-normalization"
  7.   exclude-result-prefixes="sy msfeednorm"
  8.   >
  9.  
  10. <!-- Shared templates -->
  11.   <xsl:import href="res://msfeeds.dll/SharedNormalizer.xsl" />
  12.  
  13. <!-- Output XML UTF-8 -->
  14.   <xsl:output method="xml" encoding="utf-8" />
  15.  
  16. <!-- Entry point -->
  17.   <xsl:template match="/atom:feed">
  18.     <rss version="2.0">
  19.       <channel>
  20.  
  21.         <xsl:call-template name="_OutputXmlBase"><xsl:with-param name="value" select="@xml:base" /></xsl:call-template>
  22.         <xsl:call-template name="_OutputXmlLang"><xsl:with-param name="value" select="@xml:lang" /></xsl:call-template>
  23.         <xsl:call-template name="_OutputLanguage"><xsl:with-param name="value" select="@xml:lang" /></xsl:call-template>
  24.  
  25.         <!-- Figure out the base URL value; xml:base overrides the download URL -->
  26.         <xsl:variable name="baseChannelUrl">
  27.           <xsl:call-template name="_GetFeedBaseUrl">
  28.             <xsl:with-param name="downloadUrl" select="$downloadUrl" />
  29.             <xsl:with-param name="rootNode" select="." />
  30.           </xsl:call-template>
  31.         </xsl:variable>
  32.  
  33.         <!-- Try to find the main link - one that has an href pointing to html and with type alternate -->
  34.         <xsl:variable name="mainLink" select="atom:link[(@rel = 'alternate' or @rel = '' or not(@rel)) and (@type = 'text/html' or @type = '' or not(@type))]" />
  35.  
  36.         <!-- Combine base URL with the main link -->
  37.         <xsl:variable name="channelLinkUrl">
  38.           <xsl:call-template name="_CompleteUrlTwoBase">
  39.             <xsl:with-param name="baseUrl1" select="$baseChannelUrl" />
  40.             <xsl:with-param name="baseUrl2" select="$mainLink/@xml:base" />
  41.             <xsl:with-param name="Url" select="$mainLink/@href" />
  42.           </xsl:call-template>
  43.         </xsl:variable>
  44.  
  45.         <xsl:if test="$mainLink">
  46.           <xsl:call-template name="_OutputLink"><xsl:with-param name="value" select="$channelLinkUrl" /></xsl:call-template>
  47.         </xsl:if>
  48.  
  49.         <xsl:if test="atom:logo">
  50.           <xsl:variable name="logoImageUrl">
  51.             <xsl:call-template name="_CompleteUrlTwoBase">
  52.               <xsl:with-param name="baseUrl1" select="$baseChannelUrl" />
  53.               <xsl:with-param name="baseUrl2" select="atom:logo/@xml:base" />
  54.               <xsl:with-param name="Url" select="atom:logo" />
  55.             </xsl:call-template>
  56.           </xsl:variable>
  57.           <xsl:call-template name="_OutputImage">
  58.             <xsl:with-param name="url" select="$logoImageUrl" />
  59.             <xsl:with-param name="title" select="atom:title" />
  60.             <xsl:with-param name="titleType" select="atom:title/@type" />
  61.             <xsl:with-param name="link" select="$channelLinkUrl" />
  62.           </xsl:call-template>
  63.         </xsl:if>
  64.  
  65.         <!-- Build a list of referenced nodes from cf:sort and cf:group -->
  66.         <xsl:variable name="cfReferences">
  67.           <xsl:call-template name="_BuildCfReferenceList"><xsl:with-param name="value" select="." /></xsl:call-template>
  68.         </xsl:variable>
  69.  
  70.         <xsl:apply-templates select="*" mode="channel">
  71.           <xsl:with-param name="baseChannelUrl" select="$baseChannelUrl" />
  72.         </xsl:apply-templates>
  73.  
  74.         <xsl:apply-templates select="atom:entry">
  75.           <xsl:with-param name="baseChannelUrl" select="$baseChannelUrl" />
  76.           <xsl:with-param name="references" select="$cfReferences" />
  77.         </xsl:apply-templates>
  78.  
  79.       </channel>
  80.     </rss>
  81.   </xsl:template>
  82.  
  83. <!-- Channel processing -->
  84.   <xsl:template match="*" mode="channel">
  85.     <xsl:param name="baseChannelUrl" />
  86.     <xsl:variable name="isFirst">
  87.       <xsl:call-template name="_IsFirstChildOfItsKind"><xsl:with-param name="value" select="." /></xsl:call-template>
  88.     </xsl:variable>
  89.     <xsl:choose>
  90.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'updated'">
  91.         <xsl:if test="$isFirst = 'true'">
  92.           <xsl:call-template name="_OutputAtomUpdated"><xsl:with-param name="value" select="." /><xsl:with-param name="type" select="@type" /></xsl:call-template>
  93.           <xsl:call-template name="_OutputLastBuildDate"><xsl:with-param name="value" select="." /><xsl:with-param name="type" select="@type" /></xsl:call-template>
  94.         </xsl:if>
  95.         
  96.       </xsl:when>
  97.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'title' and $isFirst = 'true'">
  98.         <xsl:call-template name="_OutputTitle">
  99.           <xsl:with-param name="value" select="." />
  100.           <xsl:with-param name="type" select="@type" />
  101.         </xsl:call-template>
  102.       </xsl:when>
  103.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'author'">
  104.         <!-- First one gets converted to managing Editor -->
  105.         <xsl:if test="$isFirst = 'true'">
  106.           <xsl:variable name="manEditor">
  107.             <xsl:call-template name="_ConvertAtomAuthorToAuthor">
  108.               <xsl:with-param name="name" select="atom:name" />
  109.               <xsl:with-param name="email" select="atom:email" />
  110.             </xsl:call-template>
  111.           </xsl:variable>
  112.           <xsl:call-template name="_OutputManagingEditor"><xsl:with-param name="value" select="$manEditor" /></xsl:call-template>
  113.         </xsl:if>
  114.         <!-- We also make a full copy of every atom:author -->
  115.         <xsl:call-template name="_OutputAtomAuthor">
  116.           <xsl:with-param name="name" select="atom:name" />
  117.           <xsl:with-param name="email" select="atom:email" />
  118.           <xsl:with-param name="uri" select="atom:uri" />
  119.         </xsl:call-template>
  120.       </xsl:when>
  121.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'contributor'">
  122.         <xsl:call-template name="_OutputAtomContributor">
  123.           <xsl:with-param name="name" select="atom:name" />
  124.           <xsl:with-param name="email" select="atom:email" />
  125.           <xsl:with-param name="uri" select="atom:uri" />
  126.         </xsl:call-template>
  127.       </xsl:when>
  128.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'subtitle' and $isFirst = 'true'">
  129.         <xsl:call-template name="_OutputTextDescription">
  130.           <xsl:with-param name="value" select="." />
  131.           <xsl:with-param name="type" select="@type" />
  132.         </xsl:call-template>
  133.       </xsl:when>
  134.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'id' and $isFirst = 'true'">
  135.         <xsl:call-template name="_OutputGuid">
  136.           <xsl:with-param name="value" select="." />
  137.           <xsl:with-param name="isPermaLink" select="'false'" />
  138.           <xsl:with-param name="channelGuid" select="'true'" />
  139.         </xsl:call-template>
  140.       </xsl:when>
  141.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'generator' and $isFirst = 'true'">
  142.         <xsl:call-template name="_OutputGenerator">
  143.           <xsl:with-param name="value" select="." />
  144.           <xsl:with-param name="uri" select="@uri" />
  145.           <xsl:with-param name="version" select="@version" />
  146.         </xsl:call-template>
  147.       </xsl:when>
  148.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'rights' and $isFirst = 'true'">
  149.         <xsl:call-template name="_OutputCopyright">
  150.           <xsl:with-param name="value" select="." />
  151.           <xsl:with-param name="type" select="@type" />
  152.         </xsl:call-template>
  153.       </xsl:when>
  154.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'link'">
  155.         <xsl:call-template name="_OutputAtomLink">
  156.           <xsl:with-param name="href" select="@href" />
  157.           <xsl:with-param name="rel" select="@rel" />
  158.           <xsl:with-param name="type" select="@type" />
  159.           <xsl:with-param name="title" select="@title" />
  160.           <xsl:with-param name="hreflang" select="@hreflang" />
  161.           <xsl:with-param name="length" select="@length" />
  162.           <xsl:with-param name="xmlBase" select="@xml:base" />
  163.         </xsl:call-template>
  164.       </xsl:when>
  165.       <!-- First pair of updateFrequency and updatePeriod gets converted to ttl; all sy:* nodes are preserved as extensions -->
  166.       <xsl:when test="namespace-uri(.) = $_NSsy and local-name(.) = 'updatePeriod' and $isFirst = 'true'">
  167.         <xsl:if test="../sy:updateFrequency">
  168.           <xsl:call-template name="_ConvertUpdatesToTtl">
  169.             <xsl:with-param name="updatePeriod" select="string(.)" />
  170.             <xsl:with-param name="updateFrequency" select="string(../sy:updateFrequency)" />
  171.           </xsl:call-template>
  172.         </xsl:if>
  173.         <xsl:call-template name="_OutputExtension"><xsl:with-param name="value" select="." /></xsl:call-template>
  174.       </xsl:when>
  175.       <xsl:when test="namespace-uri(.) = $_NScf and local-name(.) = 'treatAs'">
  176.         <xsl:if test="$isFirst = 'true'">
  177.           <xsl:call-template name="_OutputCfTreatAs"><xsl:with-param name="value" select="." /></xsl:call-template>
  178.         </xsl:if>
  179.       </xsl:when>
  180.       <xsl:when test="namespace-uri(.) = $_NScf and local-name(.) = 'listinfo'">
  181.         <xsl:if test="$isFirst = 'true'">
  182.           <xsl:call-template name="_OutputCfListinfo"><xsl:with-param name="value" select="." /></xsl:call-template>
  183.         </xsl:if>
  184.       </xsl:when>
  185.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'entry'">
  186.         <!-- Do nothing here for items -->
  187.       </xsl:when>
  188.       <!-- Copy extension nodes -->
  189.       <xsl:when test="namespace-uri(.) != $_NSatom1 and namespace-uri(.) != ''">
  190.         <xsl:call-template name="_OutputExtension"><xsl:with-param name="value" select="." /></xsl:call-template>
  191.       </xsl:when>
  192.     </xsl:choose>
  193.   </xsl:template>
  194.  
  195. <!-- Item processing -->
  196.   <xsl:template match="atom:entry">
  197.     <xsl:param name="baseChannelUrl" />
  198.     <xsl:param name="references" />
  199.     <item>
  200.  
  201.       <xsl:call-template name="_OutputXmlBase"><xsl:with-param name="value" select="@xml:base" /></xsl:call-template>
  202.  
  203.       <xsl:call-template name="_OutputXmlLang"><xsl:with-param name="value" select="@xml:lang" /></xsl:call-template>
  204.  
  205.       <!-- Item's base URL stacks onto channel's base URL -->
  206.       <xsl:variable name="baseChannelItemUrl">
  207.         <xsl:call-template name="_CombineUrls">
  208.           <xsl:with-param name="baseUrl" select="$baseChannelUrl" />
  209.           <xsl:with-param name="relUrl" select="@xml:base" />
  210.         </xsl:call-template>
  211.       </xsl:variable>
  212.  
  213.       <!-- Try to find the main link - one that has an href pointing to html and with type alternate -->
  214.       <xsl:variable name="mainLink" select="atom:link[(@rel = 'alternate' or @rel = '' or not(@rel)) and (@type = 'text/html' or @type = '' or not(@type))]" />
  215.  
  216.       <!-- Output link -->
  217.       <xsl:if test="$mainLink">
  218.         <!-- Combine base URL with the main link -->
  219.         <xsl:variable name="itemLinkUrl">
  220.           <xsl:call-template name="_CompleteUrlTwoBase">
  221.             <xsl:with-param name="baseUrl1" select="$baseChannelItemUrl" />
  222.             <xsl:with-param name="baseUrl2" select="$mainLink/@xml:base" />
  223.             <xsl:with-param name="Url" select="$mainLink/@href" />
  224.           </xsl:call-template>
  225.         </xsl:variable>
  226.         <xsl:call-template name="_OutputLink"><xsl:with-param name="value" select="$itemLinkUrl" /></xsl:call-template>
  227.       </xsl:if>
  228.  
  229.       <xsl:apply-templates select="*" mode="item">
  230.         <xsl:with-param name="baseItemUrl" select="$baseChannelItemUrl" />
  231.         <xsl:with-param name="references" select="$references" />
  232.       </xsl:apply-templates>
  233.  
  234.     </item>
  235.   </xsl:template>
  236.   
  237.   <xsl:template match="*" mode="item">
  238.     <xsl:param name="baseItemUrl" />
  239.     <xsl:param name="references" />
  240.     <xsl:variable name="isFirst">
  241.       <xsl:call-template name="_IsFirstChildOfItsKind"><xsl:with-param name="value" select="." /></xsl:call-template>
  242.     </xsl:variable>
  243.     <xsl:choose>
  244.       <!-- Process items -->
  245.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'title' and $isFirst = 'true'">
  246.         <xsl:call-template name="_OutputTitle">
  247.           <xsl:with-param name="value" select="." />
  248.           <xsl:with-param name="type" select="@type" />
  249.         </xsl:call-template>
  250.       </xsl:when>
  251.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'link' and @rel = 'enclosure' and (@href or @length or @type)">
  252.         <xsl:variable name="enclosureUrl">
  253.           <xsl:call-template name="_CompleteUrlTwoBase">
  254.             <xsl:with-param name="baseUrl1" select="$baseItemUrl" />
  255.             <xsl:with-param name="baseUrl2" select="@xml:base" />
  256.             <xsl:with-param name="Url" select="@href" />
  257.           </xsl:call-template>
  258.         </xsl:variable>
  259.         <xsl:call-template name="_OutputEnclosure">
  260.           <xsl:with-param name="url" select="$enclosureUrl" />
  261.           <xsl:with-param name="length" select="@length" />
  262.           <xsl:with-param name="type" select="@type" />
  263.         </xsl:call-template>
  264.         <!-- We also make a full copy of the atom:link -->
  265.         <xsl:call-template name="_OutputAtomLink">
  266.           <xsl:with-param name="href" select="@href" />
  267.           <xsl:with-param name="rel" select="@rel" />
  268.           <xsl:with-param name="type" select="@type" />
  269.           <xsl:with-param name="title" select="@title" />
  270.           <xsl:with-param name="hreflang" select="@hreflang" />
  271.           <xsl:with-param name="length" select="@length" />
  272.           <xsl:with-param name="xmlBase" select="@xml:base" />
  273.         </xsl:call-template>
  274.       </xsl:when>
  275.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'link'">
  276.         <xsl:call-template name="_OutputAtomLink">
  277.           <xsl:with-param name="href" select="@href" />
  278.           <xsl:with-param name="rel" select="@rel" />
  279.           <xsl:with-param name="type" select="@type" />
  280.           <xsl:with-param name="title" select="@title" />
  281.           <xsl:with-param name="hreflang" select="@hreflang" />
  282.           <xsl:with-param name="length" select="@length" />
  283.           <xsl:with-param name="xmlBase" select="@xml:base" />
  284.         </xsl:call-template>
  285.       </xsl:when>
  286.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'author'">
  287.         <xsl:variable name="author">
  288.           <xsl:call-template name="_ConvertAtomAuthorToAuthor">
  289.             <xsl:with-param name="name" select="atom:name" />
  290.             <xsl:with-param name="email" select="atom:email" />
  291.           </xsl:call-template>
  292.         </xsl:variable>
  293.         <xsl:call-template name="_OutputAuthor"><xsl:with-param name="value" select="$author" /></xsl:call-template>
  294.         <!-- We also make a full copy of the atom:author -->
  295.         <xsl:call-template name="_OutputAtomAuthor">
  296.           <xsl:with-param name="name" select="atom:name" />
  297.           <xsl:with-param name="email" select="atom:email" />
  298.           <xsl:with-param name="uri" select="atom:uri" />
  299.         </xsl:call-template>
  300.       </xsl:when>
  301.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'contributor'">
  302.         <xsl:call-template name="_OutputAtomContributor">
  303.           <xsl:with-param name="name" select="atom:name" />
  304.           <xsl:with-param name="email" select="atom:email" />
  305.           <xsl:with-param name="uri" select="atom:uri" />
  306.         </xsl:call-template>
  307.       </xsl:when>
  308.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'id' and $isFirst = 'true'">
  309.         <xsl:call-template name="_OutputGuid">
  310.           <xsl:with-param name="value" select="." />
  311.           <xsl:with-param name="isPermaLink" select="'false'" />
  312.         </xsl:call-template>
  313.       </xsl:when>
  314.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'updated' and $isFirst = 'true'">
  315.         <xsl:call-template name="_OutputAtomUpdated"><xsl:with-param name="value" select="." /></xsl:call-template>
  316.       </xsl:when>
  317.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'published' and $isFirst = 'true'">
  318.         <xsl:call-template name="_OutputAtomPublished"><xsl:with-param name="value" select="." /></xsl:call-template>
  319.         <xsl:call-template name="_OutputPubDate"><xsl:with-param name="value" select="." /></xsl:call-template>
  320.         <xsl:if test="not(../atom:updated)">
  321.           <xsl:call-template name="_OutputAtomUpdated"><xsl:with-param name="value" select="." /></xsl:call-template>
  322.         </xsl:if>
  323.       </xsl:when>
  324.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'category' and (@term or @scheme)">
  325.         <xsl:call-template name="_OutputCategory">
  326.           <xsl:with-param name="value" select="@term" />
  327.           <xsl:with-param name="domain" select="@scheme" />
  328.         </xsl:call-template>
  329.       </xsl:when>
  330.       <!-- Handle content: printable goes into description; non-printable is preserved -->
  331.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'content' and $isFirst = 'true'">
  332.         <xsl:choose>
  333.           <xsl:when test="(@src = '' or not(@src)) and (@type = '' or not(@type) or @type = 'text' or @type = 'html' or @type = 'xhtml')">
  334.             <xsl:variable name="baseContentUrl">
  335.               <xsl:call-template name="_CombineUrls">
  336.                 <xsl:with-param name="baseUrl" select="$baseItemUrl" />
  337.                 <xsl:with-param name="relUrl" select="@xml:base" />
  338.               </xsl:call-template>
  339.             </xsl:variable>
  340.             <xsl:call-template name="_OutputDescription">
  341.               <xsl:with-param name="value" select="." />
  342.               <xsl:with-param name="type" select="@type" />
  343.               <xsl:with-param name="baseUrl" select="$baseContentUrl" />
  344.             </xsl:call-template>
  345.           </xsl:when>
  346.           <xsl:otherwise>
  347.             <!-- NOTE: We don't understand content so we just won't touch it -->
  348.             <xsl:call-template name="_OutputExtension">
  349.               <xsl:with-param name="value" select="." />
  350.             </xsl:call-template>
  351.           </xsl:otherwise>
  352.         </xsl:choose>
  353.       </xsl:when>
  354.       <!-- Handle summary: printable goes into description or atom:summary; non-printable is discarded -->
  355.       <xsl:when test="namespace-uri(.) = $_NSatom1 and local-name(.) = 'summary' and $isFirst = 'true'">
  356.         <xsl:if test="(@src = '' or not(@src)) and (@type = '' or not(@type) or @type = 'text' or @type = 'html' or @type = 'xhtml')">
  357.           <xsl:variable name="baseContentUrl">
  358.             <xsl:call-template name="_CombineUrls">
  359.               <xsl:with-param name="baseUrl" select="$baseItemUrl" />
  360.               <xsl:with-param name="relUrl" select="@xml:base" />
  361.             </xsl:call-template>
  362.           </xsl:variable>
  363.           <xsl:choose>
  364.             <xsl:when test="not(../atom:content[(@src = '' or not(@src)) and (@type = '' or not(@type) or @type = 'text' or @type = 'html' or @type = 'xhtml')])">
  365.               <xsl:call-template name="_OutputDescription">
  366.                 <xsl:with-param name="value" select="." />
  367.                 <xsl:with-param name="type" select="@type" />
  368.                 <xsl:with-param name="baseUrl" select="$baseContentUrl" />
  369.               </xsl:call-template>
  370.             </xsl:when>
  371.             <xsl:otherwise>
  372.               <xsl:call-template name="_OutputAtomSummary">
  373.                 <xsl:with-param name="value" select="." />
  374.                 <xsl:with-param name="type" select="@type" />
  375.                 <xsl:with-param name="xmlBase" select="@xml:base" />
  376.                 <xsl:with-param name="baseUrl" select="$baseContentUrl" />
  377.               </xsl:call-template>
  378.             </xsl:otherwise>
  379.           </xsl:choose>
  380.         </xsl:if>
  381.       </xsl:when>
  382.       <xsl:when test="namespace-uri(.) = $_NSslash and local-name(.) = 'comments'">
  383.         <xsl:if test="$isFirst = 'true'">
  384.           <xsl:call-template name="_OutputSlashComments"><xsl:with-param name="value" select="." /></xsl:call-template>
  385.         </xsl:if>
  386.       </xsl:when>
  387.       <xsl:when test="namespace-uri(.) = $_NSwfw and (local-name(.) = 'commentRss' or local-name(.) = 'commentRSS')">
  388.         <xsl:if test="$isFirst = 'true'">
  389.           <xsl:variable name="commentRssUrl">
  390.             <xsl:call-template name="_CompleteUrlTwoBase">
  391.               <xsl:with-param name="baseUrl1" select="$baseItemUrl" />
  392.               <xsl:with-param name="baseUrl2" select="@xml:base" />
  393.               <xsl:with-param name="Url" select="." />
  394.             </xsl:call-template>
  395.           </xsl:variable>
  396.           <xsl:call-template name="_OutputWfwCommentRSS"><xsl:with-param name="value" select="$commentRssUrl" /></xsl:call-template>
  397.         </xsl:if>
  398.       </xsl:when>
  399.       <!-- Copy extension nodes -->
  400.       <xsl:when test="namespace-uri(.) != $_NSatom1 and namespace-uri(.) != ''">
  401.         <xsl:call-template name="_OutputExtension">
  402.           <xsl:with-param name="value" select="." />
  403.           <xsl:with-param name="references" select="$references" />
  404.         </xsl:call-template>
  405.       </xsl:when>
  406.     </xsl:choose>
  407.   </xsl:template>
  408.  
  409. </xsl:stylesheet>