2013-04-24 148 views
0

我正在使用xslt(版本1.0,使用MSXSL)來轉換某些xml。通過xslt中的arregate元素屬性對組進行排序

說我的XML數據是這樣的:

<table> 
<record><name>A</name><value>a</value><size>10</size></record> 
<record><name>A</name><value>b</value><size>35</size></record> 
<record><name>A</name><value>c</value><size>60</size></record> 
<record><name>B</name><value>x</value><size>15</size></record> 
<record><name>B</name><value>y</value><size>90</size></record> 
<record><name>B</name><value>z</value><size>20</size></record> 
... 
</table> 

我的目標是:

  1. 到組由<name>
  2. 每組記錄,確定最大<size>,說maxsize
  3. 按組maxsize(降序)
  4. 每組,列表中的記錄(原順序)

那麼其結果可能是:

<table> 
<group>B<maxsize>90</maxsize> 
    <record><value>x</value><size>15</size> 
    <record><value>y</value><size>90</size> 
    <record><value>z</value><size>20</size> 
</group> 
<group>A<maxsize>60</maxsize> 
    <record><value>a</value><size>10</size> 
    <record><value>a</value><size>35</size> 
    <record><value>a</value><size>60</size> 
</group> 
</table> 

現在步驟1,2和4,我能做到這一點。但是......我怎麼能按最大尺寸排序呢?

我試着在一個包含組的變量中構建一個新的節點集。我可以創建這樣一個集合,但我只能以字符串的形式訪問它。

應該可以吧?

回答

1

在這裏你去:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="kRecord" match="record" use="name"/> 

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

    <xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:apply-templates 
     select="record[generate-id() = 
         generate-id(key('kRecord', name)[1])]" 
     mode="group"> 
     <xsl:sort select="key('kRecord', name)/size 
           [not(. &lt; key('kRecord', ../name)/size)]" 
        data-type="number" 
        order="descending" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="record" mode="group"> 
    <xsl:variable name="members" select="key('kRecord', name)" /> 
    <group> 
     <xsl:value-of select="name" /> 
     <maxsize> 
     <xsl:value-of select="$members/size[not(. &lt; $members/size)]"/> 
     </maxsize> 
     <xsl:apply-templates select="$members" /> 
    </group> 
    </xsl:template> 

    <xsl:template match="record/name" /> 
</xsl:stylesheet> 

當你的樣品輸入運行,其結果是:

<table> 
    <group> 
    B<maxsize>90</maxsize><record> 
     <value>x</value> 
     <size>15</size> 
    </record><record> 
     <value>y</value> 
     <size>90</size> 
    </record><record> 
     <value>z</value> 
     <size>20</size> 
    </record> 
    </group> 
    <group> 
    A<maxsize>60</maxsize><record> 
     <value>a</value> 
     <size>10</size> 
    </record><record> 
     <value>b</value> 
     <size>35</size> 
    </record><record> 
     <value>c</value> 
     <size>60</size> 
    </record> 
    </group> 
</table> 

順便說一句,有可能訪問構造節點設置變量,如果你使用在大多數XSLT處理器中可用的node-set()函數。我喜歡在我可以的時候避免使用node-set()函數,因爲它是非標準的,並且沒有完全的支持(並且它的名字空間在支持它的處理器上甚至不是一致的),但這裏是你如何做到的:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exslt="http://exslt.org/common" 
       exclude-result-prefixes="exslt"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="kRecord" match="record" use="name"/> 

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

    <xsl:template match="/table"> 
    <xsl:copy> 
     <xsl:variable name="groups"> 
     <xsl:apply-templates 
      select="record[generate-id() = 
         generate-id(key('kRecord', name)[1])]" 
      mode="group" /> 
     </xsl:variable> 
     <xsl:apply-templates select="exslt:node-set($groups)/*"> 
     <xsl:sort select="maxsize" data-type="number" order="descending" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="record" mode="group"> 
    <xsl:variable name="members" select="key('kRecord', name)" /> 
    <group> 
     <xsl:value-of select="name" /> 
     <maxsize> 
     <xsl:apply-templates select="$members/size" mode="max"> 
      <xsl:sort select="." data-type="number" order="descending" /> 
     </xsl:apply-templates> 
     </maxsize> 
     <xsl:apply-templates select="$members" /> 
    </group> 
    </xsl:template> 

    <xsl:template match="record/name" /> 

    <xsl:template match="*" mode="max"> 
    <xsl:if test="position() = 1"> 
     <xsl:value-of select="." /> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 
1

這種短變換(只有兩個模板,沒有模式,無變量):

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

<xsl:key name="kRecByName" match="record" use="name"/> 

<xsl:template match="/*"> 
    <table> 
    <xsl:apply-templates select= 
    "*[generate-id()=generate-id(key('kRecByName', name) 
            [not(key('kRecByName', name)/size > size)][1])]"> 
     <xsl:sort select="size" data-type="number" order="descending"/> 
    </xsl:apply-templates> 
    </table> 
</xsl:template> 

<xsl:template match="record"> 
    <group><xsl:value-of select="name"/><maxsize><xsl:value-of select="size"/></maxsize> 
    <xsl:copy-of select="key('kRecByName', name)"/> 
    </group> 
</xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔施加:

<table> 
<record><name>A</name><value>a</value><size>10</size></record> 
<record><name>A</name><value>b</value><size>35</size></record> 
<record><name>A</name><value>c</value><size>60</size></record> 
<record><name>B</name><value>x</value><size>15</size></record> 
<record><name>B</name><value>y</value><size>90</size></record> 
<record><name>B</name><value>z</value><size>20</size></record> 
... 
</table> 

產生想要的,正確的結果

<table> 
    <group>B<maxsize>90</maxsize> 
     <record> 
     <name>B</name> 
     <value>x</value> 
     <size>15</size> 
     </record> 
     <record> 
     <name>B</name> 
     <value>y</value> 
     <size>90</size> 
     </record> 
     <record> 
     <name>B</name> 
     <value>z</value> 
     <size>20</size> 
     </record> 
    </group> 
    <group>A<maxsize>60</maxsize> 
     <record> 
     <name>A</name> 
     <value>a</value> 
     <size>10</size> 
     </record> 
     <record> 
     <name>A</name> 
     <value>b</value> 
     <size>35</size> 
     </record> 
     <record> 
     <name>A</name> 
     <value>c</value> 
     <size>60</size> 
     </record> 
    </group> 
</table> 
相關問題