2009-02-03 80 views
5

我有標籤兩級(報頭和線),如簡單的XML:XSLT分組

<?xml version="1.0"?> 
<Header> 
    <line>Line 1</line> 
    <line>Line 2</line> 
    <line>Line 3</line> 
    <line>Line 4</line> 
    <line>Line 5</line> 
    <line>Line 6</line> 
    <line>Line 7</line> 
    <line>Line 8</line> 
    <line>Line 9</line> 
</Header> 

我需要組上組X的行(X = 3例如)線,從而使我的輸出如下:

<?xml version="1.0"?> 
<Header> 
    <set> 
     <line>Line 1</line> 
     <line>Line 2</line> 
     <line>Line 3</line> 
    </set> 
    <set> 
     <line>Line 4</line> 
     <line>Line 5</line> 
     <line>Line 6</line> 
    </set> 
    <set> 
     <line>Line 7</line> 
     <line>Line 8</line> 
     <line>Line 9</line> 
    </set> 
</Header> 

如何編寫一個可以進行這種轉換的XSLT?

謝謝!

Ø

+0

@otavio您可能正在使用一個越野車,不符合標準的XSLT處理器,或者更可能的是,改變了源XML文檔,或者改變了代碼。 - Dimitre Novatchev(0秒前) – 2009-02-03 17:17:18

回答

4

以下變換產生所需的結果

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

<xsl:variable name="vN" select="3"/> 

    <xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:apply-templates 
      select="line[position() mod $vN = 1]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="line"> 
    <set> 
     <xsl:apply-templates mode="copy" select= 
     ". 
     | 
     following-sibling::line[position() &lt; $vN]"/> 
    </set> 
    </xsl:template> 

    <xsl:template match="line" mode="copy"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔施加:

<Header> 
    <line>Line 1</line> 
    <line>Line 2</line> 
    <line>Line 3</line> 
    <line>Line 4</line> 
    <line>Line 5</line> 
    <line>Line 6</line> 
    <line>Line 7</line> 
    <line>Line 8</line> 
    <line>Line 9</line> 
</Header> 

結果是

<Header> 
    <set> 
    <line>Line 1</line> 
    <line>Line 2</line> 
    <line>Line 3</line> 
    </set> 
    <set> 
    <line>Line 4</line> 
    <line>Line 5</line> 
    <line>Line 6</line> 
    </set> 
    <set> 
    <line>Line 7</line> 
    <line>Line 8</line> 
    <line>Line 9</line> 
    </set> 
</Header> 

請注意以下幾點

  1. 的使用XPath mod操作,找出各組vN元素的第一line元素。

  2. 使用模式的,以便能夠通過不同的模板

+0

它的工作我改變後 的 到 的 Otavio 2009-02-03 16:16:53

1

一般在XSLT,如果你想創建一個從列表中的層次結構,你可以使用前同輩及以下同胞的關鍵字。如果在集合之間有標記條目,這很簡單。

由於在這種情況下你沒有標記,所以我想象一個解決方案可能涉及以下 - 兄弟關鍵字和mod運算符。 mod提供了集合之間的劃分。

我還沒有嘗試過,但這將是我的第一個開始。

xslt通常是理解不同關鍵字的好地方。

0

這應該是可以處理不同line元件。有需要的輸出:

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

    <xsl:template match="/Header"> 
    <Header> 
     <xsl:for-each select="line"> 
     <xsl:if test="not(number()=0) and position() mod 3 = 0"> 
      <set> 
      <xsl:variable name="pos" select="position()"/> 
      <line><xsl:value-of select="../line[position()=($pos -2)]"/></line> 
      <line><xsl:value-of select="../line[position()=($pos -1)]"/></line> 
      <line><xsl:value-of select="text()"/></line> 
      </set> 
     </xsl:if> 

     </xsl:for-each> 
    </Header> 
    </xsl:template> 

</xsl:stylesheet> 

(POS-1,$ POS-2的事情是不是很漂亮)

1

http://www.xml.com/pub/a/2003/11/05/tr.html顯示這樣使用XSLT 2.0的一個稍微不那麼醜陋的方式。關鍵因素是這一個:

<xsl:for-each-group select="*" group-ending-with="*[position() mod 3 = 0]">