XSLT对两个不同节点的子节点进行排序

时间:2014-02-24 04:38:38

标签: xml xslt

您好我是xslt的新手,我遇到了一个问题,我需要对子节点进行排序,无论他们拥有什么父节点并显示排列的内容。所以XML文件是

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<report>
    <rowsbypage>5</rowsbypage><!--added to complete the solution-->
    <contenido>
        <page>
            <pagenumber>1</pagenumber>
            <row regnum="0">
                <column name="group_id"  type="number">
                    <value><![CDATA[8]]></value>
                    <group_id type="number"><![CDATA[8]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[CTA:Financials]]></value>
                    <group_name type="text"><![CDATA[CTA:Financials]]></group_name>
                </column>
            </row>
            <row regnum="1">
                <column name="group_id"  type="number">
                    <value><![CDATA[9]]></value>
                    <group_id type="number"><![CDATA[9]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[CTA:HR]]></value>
                    <group_name type="text"><![CDATA[CTA: RH]]></group_name>
                </column>
            </row>
            <row regnum="2">
                <column name="group_id"  type="number">
                    <value><![CDATA[7]]></value>
                    <group_id type="number"><![CDATA[7]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[CTA:Accounting]]></value>
                    <group_name type="text"><![CDATA[CTA:Accounting]]></group_name>
                </column>
            </row>
            <row regnum="3">
                <column name="group_id"  type="number">
                    <value><![CDATA[2]]></value>
                    <group_id type="number"><![CDATA[2]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[CTA:Shop]]></value>
                    <group_name type="text"><![CDATA[CTA:Shop]]></group_name>
                </column>
            </row>
            <row regnum="38">
                <column name="group_id"  type="number">
                    <value><![CDATA[3]]></value>
                    <group_id type="number"><![CDATA[3]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[P:Admins]]></value>
                    <group_name type="text"><![CDATA[P:Admins]]></group_name>
                </column>
            </row>
        </page>
        <page>
            <pagenumber>2</pagenumber>
            <row regnum="39">
                <column name="group_id"  type="number">
                    <value><![CDATA[1]]></value>
                    <group_id type="number"><![CDATA[1]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[P:Sys]]></value>
                    <group_name type="text"><![CDATA[P:Sys]]></group_name>
                </column>
            </row>
            <row regnum="40">
                <column name="group_id"  type="number">
                    <value><![CDATA[5]]></value>
                    <group_id type="number"><![CDATA[5]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[P:Dir]]></value>
                    <group_name type="text"><![CDATA[P:Dir]]></group_name>
                </column>
            </row>
            <row regnum="41">
                <column name="group_id"  type="number">
                    <value><![CDATA[6]]></value>
                    <group_id type="number"><![CDATA[6]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[P:Ge]]></value>
                    <group_name type="text"><![CDATA[P:Ge]]></group_name>
                </column>
            </row>
            <row regnum="42">
                <column name="group_id"  type="number">
                    <value><![CDATA[4]]></value>
                    <group_id type="number"><![CDATA[4]]></group_id>
                </column>
                <column name="group_name"  type="text">
                    <value><![CDATA[P:Req]]></value>
                    <group_name type="text"><![CDATA[P:Req]]></group_name>
                </column>
            </row>
        </page>
    </contenido>
</report>

我需要排序:

Page 1
Group ID             Group Name
   1                 P:Sys
   2                 CTA:Shop
   3                 P:Admins
   4                 P:Req
   5                 P:Dir
Page2
Group ID             Group Name
   6                 P:Ge
   7                 CTA:Accounting
   8                 CTA:Financials
   9                 CTA:HR

我将非常感谢您的帮助,亲切的问候

感谢您在Joel和Michael的帮助下做出的回复。我以此结束了,我添加了一个标签,其中包含逐页行数和xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/" >
        <xsl:apply-templates select="report/contenido/page" />
</xsl:template>

<xsl:template name="dopaging">
        <xsl:param name="pageNumber" />
        <xsl:for-each select="../page/row" >
                <xsl:sort select="column/value" data-type="number"/>
                <xsl:choose>
                        <xsl:when test="position() &gt; ($pageNumber - 1) * /report/rowsbypage and position()  &lt;= $pageNumber * /report/rowsbypage">
                                <xsl:for-each select="column" >
                                <div><xsl:value-of select="value" /></div>
                                </xsl:for-each>
                        </xsl:when>
                </xsl:choose>
        </xsl:for-each>
</xsl:template>

<xsl:template match="pagenumber" >
        <xsl:value-of select="." />
</xsl:template>

<xsl:template match="page">
        <xsl:variable name="pageNumber" select="pagenumber" />
        <div>
                <div>Page <xsl:value-of select="$pageNumber" /></div>
                <xsl:call-template name="dopaging">
                        <xsl:with-param name="pageNumber" select="$pageNumber" />
                </xsl:call-template>
        </div>
</xsl:template>

</xsl:stylesheet>

在迈克尔的最后评论之后好了,对于每个页面一次又一次地排序所有记录,最终的XSL看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<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:output method="html" encoding="iso-8859-1" version="5.0" />
    <xsl:template match="/" >
            <xsl:variable name="rowsByPage" select="report/rowsbypage" />
            <xsl:variable name="rows">
                    <xsl:for-each select="report/contenido/page/row" >
                            <xsl:sort select="column/group_id" data-type="number" />
                            <div>
                            <xsl:for-each select="column" >
                                    <div><xsl:value-of select="value"/></div>
                            </xsl:for-each>
                            </div>
                    </xsl:for-each>
            </xsl:variable>
            <xsl:for-each select="exsl:node-set($rows)/div[position() mod $rowsByPage = 1]" >
                    <div>
                    <div>Page <xsl:value-of select="position()" /></div>
                    <xsl:for-each select=". | following-sibling::div[position() &lt; $rowsByPage]">
                            <xsl:copy-of select="." />
                    </xsl:for-each>
                    </div>
            </xsl:for-each>
    </xsl:template>

    </xsl:stylesheet>

2 个答案:

答案 0 :(得分:0)

请尝试以下代码。我不确定你的所需产量。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output cdata-section-elements="value group_id group_name"/>

    <xsl:template name="first_group">
        <xsl:variable name="page1_count" select="count(../page[1]/row)"/>
            <xsl:for-each select="../page/row">
                <xsl:sort select="column/value"/>
                <xsl:choose>
                    <xsl:when test="position() &lt;= $page1_count">
                        <xsl:copy-of select="."/>
                    </xsl:when>
                    <xsl:otherwise/>
                </xsl:choose>
            </xsl:for-each>
    </xsl:template>

    <xsl:template name="second_group">
        <xsl:variable name="page1_count" select="count(../page[1]/row)"/>
        <xsl:for-each select="../page/row">
            <xsl:sort select="column/value"/>
            <xsl:choose>
                <xsl:when test="position() &gt; $page1_count">
                    <xsl:copy-of select="."/>
                </xsl:when>
                <xsl:otherwise/>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>


    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>


    <xsl:template match="page">
        <xsl:copy>
            <xsl:apply-templates select="pagenumber"/>
            <row>
                <column>Group ID</column>
                <column>Group Name</column>
            </row>
            <xsl:choose>
                <xsl:when test="count(preceding-sibling::page) + 1 = 1">
                    <xsl:call-template name="first_group"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="second_group"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

  

输出位于html网格上。

我不太确定“html网格”是什么。以下样式表提供XML输出 - 将其转换为HTML(表格或任何其他结构)应该是相当简单的。

这里的主要问题是你需要在两个过程中执行此操作:首先,对行进行排序;然后将排序的行聚合成页面,一次5个。

XSLT 1.0(需要支持EXSLT node-set()函数:

<?xml version="1.0" encoding="utf-8"?>
<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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">

<xsl:variable name="rows">
    <xsl:for-each select="report/contenido/page/row">
    <xsl:sort select="column/group_id"/>
        <group>
            <id><xsl:value-of select="column/group_id"/></id>
            <name><xsl:value-of select="column/group_name"/></name>
        </group>
    </xsl:for-each>
</xsl:variable>

<output>
    <xsl:for-each select="exsl:node-set($rows)/group[position() mod 5 = 1]">
        <page pagenum="{position()}">
            <xsl:copy-of select=". | following-sibling::group[position() &lt; 5]"/>
        </page>
    </xsl:for-each>
</output>
</xsl:template>

</xsl:stylesheet>

应用于您的输入,结果是:

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <page pagenum="1">
      <group>
         <id>1</id>
         <name>P:Sys</name>
      </group>
      <group>
         <id>2</id>
         <name>CTA:Shop</name>
      </group>
      <group>
         <id>3</id>
         <name>P:Admins</name>
      </group>
      <group>
         <id>4</id>
         <name>P:Req</name>
      </group>
      <group>
         <id>5</id>
         <name>P:Dir</name>
      </group>
   </page>
   <page pagenum="2">
      <group>
         <id>6</id>
         <name>P:Ge</name>
      </group>
      <group>
         <id>7</id>
         <name>CTA:Accounting</name>
      </group>
      <group>
         <id>8</id>
         <name>CTA:Financials</name>
      </group>
      <group>
         <id>9</id>
         <name>CTA: RH</name>
      </group>
   </page>
</output>