将XSLT节点随机插入列表

时间:2015-03-27 08:42:25

标签: xslt

我正在尝试合并两个列表,以便帖子按日期顺序排列,广告在列表中以随机间隔添加。

据我所知......

INPUT XML(列出1博客帖子)

   <root>
      <page>
         <content createdDate="2015-01-01">Post 1</content>
      </page>
      <page>
         <content createdDate="2015-01-02">Post 2</content>
      </page>
      <page>
         <content createdDate="2015-01-03">Post 3</content>
      </page>
   </root>

INPUT XML(列表2广告)

  <root>
      <advert>
         <content>Advert 1</content>
      </advert>
      <advert>
         <content>Advert 2</content>
      </advert>
      <advert>
         <content>Advert 3</content>
      </advert>
   </root>

OUTPUT XML(随机广告插入和日期顺序的帖子)

   <root>
      <merged>
         <content createdDate="2015-01-03">Post 3</content>
      </merged>
      <merged>
         <content>Advert 2</content>
      </merged>
      <merged>
         <content createdDate="2015-01-02">Post 2</content>
      </merged>
      <merged>
         <content createdDate="2015-01-01">Post 1</content>
      </merged>
      <merged>
         <content>Advert 3</content>
      </merged>
      <merged>
         <content>Advert 1</content>
      </merged>
   </root>

XSLT

    <xsl:variable name="mergedData">
       <xsl:for-each select="$currentPage/descendant::cwsBlogItem [@isDoc and string(umbracoNaviHide) != '1']">
           <xsl:copy-of select="."/>
       </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="mergedAdverts">
            <xsl:for-each select="$adverts/descendant::cwsMediumBanner [@isDoc and string(umbracoNaviHide) != '1']">
                <xsl:copy-of select="."/>
            </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="numberOfAdverts" select="count(msxsl:node-set($mergedAdverts)/*)"/>
    <xsl:variable name="numberOfRecords" select="count(msxsl:node-set($mergedData)/*)"/>

    <msxsl:script language="JavaScript" implements-prefix="cws">
        function Random(r) { return Math.ceil(Math.random()*r); }
    </msxsl:script>

    <xsl:apply-templates select="msxsl:node-set($mergedData)/* ">
       <xsl:sort select="@createDate" order="descending" data-type="text" />
       <xsl:sort select="cws:Random($numberOfRecords + $numberOfAdverts)" order="descending"  />
    </xsl:apply-templates>   

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

我建议你这样试试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
extension-element-prefixes="exsl math">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="adverts-doc" select="document('adverts.xml')" />

<xsl:variable name="count-pages" select="count(/root/page)" />

<xsl:variable name="ads">
    <xsl:for-each select="$adverts-doc/root/advert">
        <ad rand="{floor(math:random() * ($count-pages - 1))}">
            <xsl:copy-of select="content"/>
        </ad>
    </xsl:for-each>
</xsl:variable>


<xsl:template match="/root">
    <xsl:copy>
        <xsl:apply-templates select="page">
            <xsl:sort select="content/@createdDate" data-type="text" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>     
</xsl:template>

<xsl:template match="page">
    <merged>
        <xsl:copy-of select="content"/>
    </merged>
    <xsl:variable name="i" select="position()" />
    <xsl:apply-templates select="exsl:node-set($ads)/ad[@rand = $i - 1]"/>
</xsl:template>

<xsl:template match="ad">
    <merged>
        <xsl:copy-of select="content"/>
    </merged>
</xsl:template>

</xsl:stylesheet>

这为每个广告分配0和页数-1之间的随机位置。然后,每个页面将模板应用于与其位置对应的广告(从位置0开始)。结果是所有广告最终都在第一页和最后一页之间。

注意
我使用EXSLT math:random()函数生成随机数;你将需要使用自己的处理器方法。