XSLT For-Each Wrapping every nth item in a div

时间秒杀一切 提交于 2019-12-18 07:15:27

问题


I have a series of nodes that are direct child nodes to a parent I want to loop over those nodes but have them wrapped in 'groups' of 4... I'm probably not wording this very clearly so this might help;

<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>
..and so on

Goal

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

I have tried variations on this idea - wrapping the lot in the open and closing group tags and every fourth loop drop in a new close / open pair

<div class="group">
<xsl:for-each select="$currentPage/*">

<span>
<xsl:value-of select="@nodeName" />
</span>

 <!--
            =============================================================
            After very 4th item  
            =============================================================
            -->
            <xsl:if test="position() mod 4 = 0">
              <xsl:text></div><div class="page"></xsl:text>
            </xsl:if>

        </xsl:for-each>
</div>

But essentially it seems XSLT won't let me start with a closing unmatched tag The clkoset solution I ahve found so far is a 'fix' in jquery Wrapping a div around every three divs but I would rather not rely on javascript to format the page.


回答1:


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>



回答2:


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>



回答3:


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

...


来源:https://stackoverflow.com/questions/9908488/xslt-for-each-wrapping-every-nth-item-in-a-div

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