XSLT For-Each Wrapping every nth item in a div

对着背影说爱祢 提交于 2019-11-29 11:59:14

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNumCols" select="3"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="span[position() mod $pNumCols = 1]"/>
 </xsl:template>

 <xsl:template match="span">
  <div>
   <xsl:copy-of select=
    ".|following-sibling::span[not(position() > $pNumCols -1)]"/>
  </div>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<t>
    <span class="child01">@nodename</span>
    <span class="child02">@nodename</span>
    <span class="child03">@nodename</span>
    <span class="child04">@nodename</span>
    <span class="child05">@nodename</span>
    <span class="child06">@nodename</span>
    <span class="child07">@nodename</span>
    <span class="child08">@nodename</span> .. 
    <span class="child32">@nodename</span>
    <span class="child33">@nodename</span>
</t>

produces the wanted result:

<div>
   <span class="child01">@nodename</span>
   <span class="child02">@nodename</span>
   <span class="child03">@nodename</span>
</div>
<div>
   <span class="child04">@nodename</span>
   <span class="child05">@nodename</span>
   <span class="child06">@nodename</span>
</div>
<div>
   <span class="child07">@nodename</span>
   <span class="child08">@nodename</span>
   <span class="child32">@nodename</span>
</div>
<div>
   <span class="child33">@nodename</span>
</div>

If like me you need to transform the source elements that are being divided by position, use xsl:for-each instead of xsl:copy:

 <xsl:template match="span">
   <ol>
     <xsl:for-each select=".|following-sibling::span[not(position() > $pNumCols -1)]"/>
       <li><xsl:value-of select="./text()"/></li>
     </xsl:for-each>
   </ol>
</xsl:template>

Faced by the same problem, that is wanting to output

<div class="container">
  <div class="row">
    <div class="col">...</div>
    <div class="col"/>...</div>
  </div>
  <div class="row">
  ...
  </div>
</div>

from a CXML (Collection XML) file (http://gallery.clipflair.net/collection/activities.cxml - the data behind the PivotViewer display at http://gallery.clipflair.net/activity)

I coined up the following, based on other suggestions here, but using "mode" attribute of "template" and "apply-templates" XSL tags instead which make it cleaner I believe:

<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml http://gallery.clipflair.net/collection/activities.cxml?>

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:cxml="http://schemas.microsoft.com/collection/metadata/2009"
  exclude-result-prefixes="cxml"
  >

  <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
  <xsl:param name="COLUMNS" select="2"/>

  <!-- ########################### -->

  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>ClipFlair Activities</title>
        <link rel="stylesheet" type="text/css" href="style.css"/>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <!-- ########################### -->

  <xsl:template match="cxml:Collection">
    <div class="container">
      <xsl:apply-templates/>
    </div>
  </xsl:template>

  <!-- ########################### -->

  <xsl:template match="cxml:Items">
    <xsl:apply-templates select="cxml:Item[position() mod $COLUMNS = 1]" mode="row"/>
  </xsl:template>

  <!-- ########################### -->

  <xsl:template match="cxml:Item" mode="row">
    <div class="row">
      <div>----------</div>
      <xsl:apply-templates select=".|following-sibling::cxml:Item[position() &lt; $COLUMNS]" mode="col"/>
    </div>
  </xsl:template>

  <xsl:template match="cxml:Item" mode="col">
    <xsl:variable name="URL" select="@Href"/>
    <xsl:variable name="FILENAME" select="cxml:Facets/cxml:Facet[@Name='Filename']/cxml:String/@Value"/>
    <div class="col">
      <xsl:value-of select="$FILENAME"/>  ---  <xsl:value-of select="$URL"/>
    </div>
  </xsl:template>

  <!-- ########################### -->

  <xsl:template match="*">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="text()|@*">
  </xsl:template>

</xsl:stylesheet>

the output from the above when run in Altova XMLSpy tool (note that it uses altova_samplexml processor instruction to find the XML data) is:


2DaysInParis-OpenActivity-CapRev-FR-EN.clipflair --- http://studio.clipflair.net/?activity=2DaysInParis-OpenActivity-CapRev-FR-EN.clipflair

Abu_Dukhan-CapRev-A1-AR.clipflair --- http://studio.clipflair.net/?activity=Abu_Dukhan-CapRev-A1-AR.clipflair


----------

AFarewellToArms-RevCap-C2-EN.clipflair --- http://studio.clipflair.net/?activity=AFarewellToArms-RevCap-C2-EN.clipflair

agComhaireamhCountingRND.clipflair --- http://studio.clipflair.net/?activity=agComhaireamhCountingRND.clipflair


----------

Al-imtihan-CapRev-B1-AR.clipflair --- http://studio.clipflair.net/?activity=Al-imtihan-CapRev-B1-AR.clipflair

AlBar-Cap-B1-B2-IT.clipflair --- http://studio.clipflair.net/?activity=AlBar-Cap-B1-B2-IT.clipflair

...
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!