在转换之前预先排序xml的问题

时间:2012-01-26 16:10:05

标签: xml xslt xpath

在stackoverflow上使用另一个代码示例,我们有一个带有页眉和页脚的分页打印报告(是的,那个老栗子)很好地工作,做这样的事情(其中RESULTS_ROW有多个子节点):

<xsl:variable name="n" select="number(4)"/>

<xsl:template match="RESULTS">
<body>
<div id="page">
  <output>
    <xsl:apply-templates select="RESULTS_ROW"/>
  </output>
</div>      
</body>
</xsl:template>

<xsl:template match="RESULTS_ROW">              
    <p/>
        [HTML FOR PAGE START]
        <br/>
    <xsl:for-each select=". | following-sibling::RESULTS_ROW[position() &lt; $n]">
        <xsl:value-of select="ITEM43"/><!--Lots more goes in here -->
            <br/>
    </xsl:for-each>
    [HTML FOR PAGE END]
        <p/>
</xsl:template>

问题出现了需要在其子节点值(ITEM43)之前对其进行排序转换为4个元素的块之外,否则排序不考虑所有子节点节点

输出目前类似于

[HTML FOR PAGE START]
North
West
North
River
[HTML FOR PAGE END]

[HTML FOR PAGE START]
West
North
River
North
[HTML FOR PAGE END]

我希望节点在分成组之前完成排序,例如:

[HTML FOR PAGE START]
North
North
North
North
[HTML FOR PAGE END]

[HTML FOR PAGE START]
River    
River    
West
West
[HTML FOR PAGE END]

我已经尝试了一些我不太能干的XSL大脑可以想到的但是各种排序,使用模式将多个模板应用到同一个节点,复制,创建包含节点值的变量等 - 似乎没什么用。

任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:0)

您应该能够将xsl:sort添加到xsl:apply-templates以获得&#34; RESULTS_ROW&#34;:

  <xsl:template match="RESULTS">
    <body>
      <div id="page">
        <output>
          <xsl:apply-templates select="RESULTS_ROW">
            <xsl:sort select="someElem" data-type="text" order="ascending"/>
          </xsl:apply-templates>
        </output>
      </div>      
    </body>
  </xsl:template>

您需要更改select,可能需要更改data-typeorder,具体取决于您的输入和所需的输出。

答案 1 :(得分:0)

编辑是的,经过一些决定并确切地检查了following-sibling我认为我已经找到了解决方案:

following-sibling将始终从原始文档处理,而不是您当前排序的顺序。这意味着当您打印出接下来的4个节点时,它将占用原始文档中的接下来的4个节点并且不符合排序顺序。

您需要做的是在应用4行模板之前对节点列表进行排序(参见下面的代码示例)。

现在使用包含新文档的字符串填充变量SortedResults,并根据需要进行排序。通过使用node-set(),您可以将其转换回XML,然后应用模板。

原始RESULTS模板中还有一个问题会影响您的搜索结果。您在每一行上调用apply-templates,因此在文档中的每一行之后输出接下来的四个兄弟。这可以通过前面显示的mod运算符来解决,以确保仅为每第四行输出结果。

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:exslt="http://exslt.org/common" extension-element-prefixes="exslt">

<xsl:variable name="n" select="number(4)"/>

<xsl:template match="RESULTS">
    <xsl:variable name="SortedResults">
        <xsl:apply-templates select="RESULTS_ROW" mode="sort">
            <xsl:sort select="ITEM43"/>
        </xsl:apply-templates>
    </xsl:variable>

    <xsl:variable name="SortedResultsNodeSet" select="exslt:node-set($SortedResults)" />

    <body>
        <div id="page">
            <output>
                <xsl:apply-templates select="$SortedResultsNodeSet/RESULTS_ROW[position() mod $n = 1]" />
            </output>
        </div>
    </body>
</xsl:template>

<xsl:template match="RESULTS_ROW" mode="sort">
    <xsl:copy-of select="current()"/>
</xsl:template>

<xsl:template match="RESULTS_ROW">

    <p/>
    [HTML FOR PAGE START]
    <br/>
    <xsl:for-each select=". | following-sibling::RESULTS_ROW[position() &lt; $n]">
        <xsl:value-of select="ITEM43"/>
        <br/>
    </xsl:for-each>
    [HTML FOR PAGE END]
    <p/>

</xsl:template>

</xsl:stylesheet>

请注意已添加的其他命名空间,以便可以使用node-set()扩展方法。