XSLT For-Each Wrapping every nth item in a div

前端 未结 3 595
执笔经年
执笔经年 2020-12-20 00:42

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 v

相关标签:
3条回答
  • 2020-12-20 01:19

    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>
    
    0 讨论(0)
  • 2020-12-20 01:35

    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
    
    ...
    
    0 讨论(0)
  • 2020-12-20 01:40

    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>
    
    0 讨论(0)
提交回复
热议问题