2016-01-08 49 views
0

我需要一個可轉換以下XML的XSLT 1.0。XSLT 1.0對XML進行排序和分組

<Record> 
    <Row> 
    <Name>AAA</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>BBB</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>CCC</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>DDD</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>EEE</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>FFF</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
    <Row> 
    <Name>GGG</Name> 
    <Surname>Surname1</Surname> 
    </Row> 
    <Row> 
    <Name>HHH</Name> 
    <Surname>Surname2</Surname> 
    </Row> 
</Record> 

我期待的輸出是:

<Output> 
    <Recordset1> 
    <Record> 
     <Name>AAA</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>CCC</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset1> 
    <Record> 
     <Name>EEE</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>GGG</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset2> 
    <Record> 
     <Name>BBB</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>DDD</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
    <Recordset2> 
    <Record> 
     <Name>FFF</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>HHH</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
</Output> 

的條件是:

  1. Recordset1應該包含Surname1節點

  2. Recordset2應該包含Surname2節點

  3. 輸出結果應按姓氏排序

  4. 每個記錄集最多有2條記錄。

回答

0

這可能對你有所幫助。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt" 
exclude-result-prefixes="msxml"> 
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

<xsl:key match="Row" name="rows" use="Surname"/> 

<xsl:template match="Record"> 
    <Output> 
    <xsl:for-each select="Row[generate-id(.) = generate-id(key('rows', Surname)[1])]"> 
     <xsl:sort select="Surname" data-type="text" order="ascending"/> 

     <xsl:variable name="Recordset" select="concat('Recordset',position())"/> 

     <xsl:variable name="Rows"> 
     <xsl:copy-of select="key('rows', Surname)"/> 
     </xsl:variable> 

     <xsl:variable name="RowList" select="msxml:node-set($Rows)"/> 

     <xsl:for-each select="$RowList/Row[position() mod 2 = 1]"> 
     <xsl:element name="{$Recordset}"> 
      <Record> 
      <xsl:copy-of select="./*"/> 
      </Record> 
      <xsl:if test="following-sibling::Row[1]/*"> 
      <Record> 
       <xsl:copy-of select="following-sibling::Row[1]/*"/> 
      </Record> 
      </xsl:if> 
     </xsl:element> 
     </xsl:for-each> 

    </xsl:for-each> 
    </Output> 
</xsl:template> 
</xsl:stylesheet> 
+0

你想象究竟是什麼這樣做:'的'? –

+1

這是您之前向我指出的Muenchian方法。我只是簡化了它的每個部分,如下所示:對於每個行Surname,找到具有該姓的第一個Row實例。所以,如果當前的行是第一個實例,那麼做東西。很好的問題。順便說一句,這段代碼工作得很好。 – Bluewood66

+0

「*對於每個行姓可以找到第一個具有該姓氏的Row實例。*」這不是您的「簡化」。它查找**的整個文本值**等於具有該姓氏的第一個Row實例的文本值的每一行。這很容易導致重複。 –

0

有一些技巧,以這樣的:

  1. 選擇不同的姓氏。
  2. 將姓氏記錄分組。
  3. 子集2中的姓氏記錄。
  4. 根據不同的姓氏索引創建動態元素名稱。

這個樣式表解決了這些問題:

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

    <xsl:template match="/Record"> 
    <Output> 
     <xsl:apply-templates select="//Row[not(./Surname=preceding::Surname)]/Surname" mode="group"> 
     <xsl:sort select="Surname" /> 
     </xsl:apply-templates> 
    </Output> 
    </xsl:template> 

    <xsl:template match="Surname" mode="group"> 
    <xsl:variable name="surname" select="./text()" /> 
    <xsl:variable name="surnameIndex" select="position()" /> 
    <xsl:variable name="surnameGroup" select="/Record/Row[Surname/text()=$surname]" /> 
    <xsl:for-each select="$surnameGroup"> 
     <xsl:variable name="index" select="position()" /> 
     <!-- only create a new record set on the first (or only) member of the output pair --> 
     <xsl:if test="$index mod 2=1"> <!-- positions are 1 based, not 0 based --> 
     <xsl:element name="Recordset{$surnameIndex}"> 
      <!-- alternatively, use xsl:copy-of --> 
      <xsl:apply-templates select="$surnameGroup[$index]" mode="record" /> 
      <xsl:apply-templates select="$surnameGroup[$index+1]" mode="record" /> 
     </xsl:element> 
     </xsl:if> 
    </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="Row" mode="record"> 
    <Record> 
     <Name><xsl:value-of select="Name" /></Name> 
     <Surname><xsl:value-of select="Surname" /></Surname> 
    </Record> 
    </xsl:template> 

</xsl:stylesheet> 

對您輸入文檔應用該樣式表的輸出是:

<?xml version="1.0" encoding="UTF-8" ?> 
<Output> 
    <Recordset1> 
    <Record> 
     <Name>AAA</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>CCC</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset1> 
    <Record> 
     <Name>EEE</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    <Record> 
     <Name>GGG</Name> 
     <Surname>Surname1</Surname> 
    </Record> 
    </Recordset1> 
    <Recordset2> 
    <Record> 
     <Name>BBB</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>DDD</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
    <Recordset2> 
    <Record> 
     <Name>FFF</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    <Record> 
     <Name>HHH</Name> 
     <Surname>Surname2</Surname> 
    </Record> 
    </Recordset2> 
</Output> 
+0

這不是一個好的答案 - 看到這裏爲什麼:http://www.jenitennison.com/xslt/grouping/muenchian.html –

+0

@ michael.hor257k你是對的,它是一個很好的答案,因爲它解決了給定的問題,同時劃分@羅蘭德遇到的不同問題。如果您擔心'prior'的使用對於確定不同值的效率太低,則可以在第一個模板中輕鬆地替換另一種方法。 – vallismortis