简体   繁体   English

XSLT 1.0:过滤、排序和分页节点集

[英]XSLT 1.0: Filter, Sort, and page a nodeset

Given the following XML:给定以下 XML:

<A>
  <Photos>
    <Photo>
      <PhotoID>142</PhotoID>
      <PhotoTitle>A</PhotoTitle>
      <Comment />
    </Photo>
    <Photo>
      <PhotoID>143</PhotoID>
      <PhotoTitle>B</PhotoTitle>
      <Comment />
    </Photo>
    <Photo>
      <PhotoID>144</PhotoID>
      <PhotoTitle>C</PhotoTitle>
      <Comment />
    </Photo>
    <Photo>
      <PhotoID>145</PhotoID>
      <PhotoTitle>D</PhotoTitle>
      <Comment />
    </Photo>
    <Photo>
      <PhotoID>146</PhotoID>
      <PhotoTitle>E</PhotoTitle>
      <Comment />
    </Photo>
    <Photo>
      <PhotoID>195</PhotoID>
      <PhotoTitle>F</PhotoTitle>
      <Comment>Foo</Comment>
    </Photo>
    <Photo>
      <PhotoID>196</PhotoID>
      <PhotoTitle>G</PhotoTitle>
      <Comment>Bar</Comment>
    </Photo>
    <Photo>
      <PhotoID>197</PhotoID>
      <PhotoTitle>H</PhotoTitle>
      <Comment>Baz</Comment>
    </Photo>
    <Photo>
      <PhotoID>199</PhotoID>
      <PhotoTitle>F</PhotoTitle>
      <Comment>qux</Comment>
    </Photo>
  </Photos>
</A>

I'd like to get HTML output similar to the following:我想获得类似于以下内容的 HTML 输出:

<div id="photoPage" class="page">
    <!-- Page Header Goes Here -->
    <div>
        <h2>Page Title Goes Here</h2>
        <div class="photoBox">
            <!-- Image URL goes here -->
            <div>
                <div>
                  F
                </div>
                <div>
                  Foo
                </div>
            </div>
        </div>  
        <div class="photoBox">
            <!-- Image URL goes here -->
            <div>
                <div>
                  F
                </div>
                <div>
                  Qux
                </div>
            </div>
        </div>  
    </div>
    <!-- Page Footer Goes Here -->
</div>
<div id="photoPage" class="page">
    <!-- Page Header Goes Here -->
    <div>
        <h2>Page Title Goes Here</h2>
        <div class="photoBox">
            <!-- Image URL goes here -->
            <div>
                <div>
                  G
                </div>
                <div>
                  Bar
                </div>
            </div>
        </div>  
        <div class="photoBox">
            <!-- Image URL goes here -->
            <div>
                <div>
                  H
                </div>
                <div>
                  Baz
                </div>
            </div>
        </div>  
    </div>
    <!-- Page Footer Goes Here -->
</div>

In summary, I'm trying to filter to the photos that only include those which have a title of "F", "G", or "H", sorted by title and id, and then split into groups of two.总而言之,我试图筛选出仅包含标题为“F”、“G”或“H”的照片,按标题和 ID 排序,然后分成两组。 I've been able to accomplish filtering and sorting, but not paging, or paging but not filtering and sorting, but I haven't been able to do all three.我已经能够完成过滤和排序,但不能完成分页,或者分页但不能完成过滤和排序,但我还没有能够做到这三个。

For reference, I'm attempting to do paging similar to this solution .作为参考,我正在尝试进行类似于此解决方案的分页。

Here's the approach that's not working:这是不起作用的方法:

<xsl:template name="Photos">    
    <xsl:copy>
        <xsl:apply-templates select="//Photos[Photo/PhotoTitle = 'F' or Photo/PhotoTitle = 'G' or Photo/PhotoTitle = 'H']">
        <xsl:sort select="PhotoTitle"/>
        <xsl:sort select="PhotoID"/>
      </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="Photos">
    <xsl:param name="pageSize" select="2"></xsl:param>
    <xsl:for-each select="//Photos/Photo[position() mod $pageSize = 1]">
      <div id="photoPage" class="page">
        <div>
          <h2>Title</h2>
          <xsl:apply-templates select="self::*|following-sibling::*[position() &lt; $pageSize]">
          </xsl:apply-templates>
        </div>
      </div>
    </xsl:for-each>
</xsl:template>

<xsl:template match="Photo">
    <div class="photoBox">
      <!-- img tag -->
      <div>
        <div>
          <xsl:value-of select="./PhotoTitle"/>
        </div>
        <div>
          <xsl:value-of select="./Comment"/>
        </div>
      </div>
    </div>
</xsl:template>

The idea is that I explicitly call the first template, which should filter and sort the Photos element, applying the second template, which splits and wraps the Photo elements into two per page, and applies the third template, which outputs and individual Photo.这个想法是我明确调用第一个模板,它应该过滤和排序照片元素,应用第二个模板,将照片元素拆分并包装成每页两个,并应用第三个模板,输出单个照片。

The results I'm currently getting are neither filtered nor sorted, but are split appropriately.我目前得到的结果既没有过滤也没有排序,而是适当地分割。 I suspect that is due to the Photos template matching separately from the template that I explicitly call.我怀疑这是由于照片模板与我明确调用的模板分开匹配。

The idea is that I explicitly call the first template这个想法是我明确调用第一个模板

I see no such call in the code you have posted.我在您发布的代码中没有看到这样的调用。 And the second template does xsl:for-each selecting all Photo s, with no filtering by Title .第二个模板执行xsl:for-each选择所有Photo s,没有按Title过滤。

The other problem with your approach is that you cannot use the following-sibling axis without copying the filtered nodes first (and, since you're using XSLT 1.0, converting the resulting tree fragment to a node-set, so that it can be processed in second pass).您的方法的另一个问题是,您不能在不首先复制过滤节点的情况下使用following-sibling轴(并且,由于您使用的是 XSLT 1.0,因此将生成的树片段转换为节点集,以便可以对其进行处理)在第二次通过)。

You also have several syntax errors.您还有几个语法错误。

Try this as your starting point:试试这个作为你的起点:

XSLT 1.0 XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:strip-space elements="*"/>

<xsl:template match="A"> 
    <html>
        <body>
            <xsl:apply-templates/>
        </body>
    </html>
</xsl:template>

<xsl:template match="Photos"> 
    <xsl:param name="pageSize" select="2"/>
    <!-- first pass -->
    <xsl:variable name="photos">
        <xsl:for-each select="Photo[PhotoTitle = 'F' or PhotoTitle = 'G' or PhotoTitle = 'H']">
            <xsl:sort select="PhotoTitle"/>
            <xsl:sort select="PhotoID" data-type="number"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:variable>
    <!-- output -->
    <xsl:for-each select="exsl:node-set($photos)/Photo[position() mod $pageSize = 1]">
        <div id="photoPage" class="page">
            <div>
                <h2>Title</h2>
                <xsl:apply-templates select=". | following-sibling::Photo[position() &lt; $pageSize]"/>
            </div>
        </div>
        </xsl:for-each>
</xsl:template>

<xsl:template match="Photo">
    <div class="photoBox">
      <!-- img tag -->
      <div>
        <div>
          <xsl:value-of select="PhotoTitle"/>
        </div>
        <div>
          <xsl:value-of select="Comment"/>
        </div>
      </div>
    </div>
</xsl:template>

</xsl:stylesheet>

Applied to your example input, the result will be:应用于您的示例输入,结果将是:

<html>
   <body>
      <div id="photoPage" class="page">
         <div>
            <h2>Title</h2>
            <div class="photoBox">
               <div>
                  <div>F</div>
                  <div>Foo</div>
               </div>
            </div>
            <div class="photoBox">
               <div>
                  <div>F</div>
                  <div>qux</div>
               </div>
            </div>
         </div>
      </div>
      <div id="photoPage" class="page">
         <div>
            <h2>Title</h2>
            <div class="photoBox">
               <div>
                  <div>G</div>
                  <div>Bar</div>
               </div>
            </div>
            <div class="photoBox">
               <div>
                  <div>H</div>
                  <div>Baz</div>
               </div>
            </div>
         </div>
      </div>
   </body>
</html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM