2012-07-03 54 views
1

我想寫一個xsl轉換,但是卡在「counter」部分。 這基本上就是我想做的事:XSL計數器循環轉換

輸入文件:

<?xml version="1.0" encoding="utf-8" ?> 
<root> 
    <Pallets> 
    <Pallet> 
     <Line> 
     <Product>test</Product> 
     </Line> 
     <Line> 
     <Product>test2</Product> 
     </Line> 
    </Pallet> 
    <Pallet> 
     <Line> 
     <Product>test_1</Product> 
     </Line> 
     <Line> 
     <Product>test_2</Product> 
     </Line> 
    </Pallet> 
    </Pallets> 
</root> 

而這正是我想要的輸出是:

<?xml version="1.0" encoding="utf-8"?> 
<Result> 
    <Pallet> 
    <ID>2</ID> ==> This is a counter that increments starting from 2 
    <ID2>1</ID2> ==> Always "1" 
    <Line> 
     <ID>3</ID> ==> The counter from above that increments 
     <ParentID>2</ParentID> ==> PalletID (ID from above the loop) 
     <Name>test</Name> 
    </Line> 
    <Line> 
     <ID>4</ID> ==> The counter from above that increments 
     <ParentID>2</ParentID> ==> PalletID 
     <Name>test2</Name> 
    </Line> 
    </Pallet> 
    <Pallet> 
    <ID>5</ID> ==> The counter from above that increments 
    <ID2>1</ID2> ==> Always "1" 
    <Line> 
     <ID>6</ID> ==> The counter from above that increments 
     <ParentID>5</ParentID> ==> PalletID 
     <Name>test_1</Name> 
    </Line> 
    <Line> 
     <ID>7</ID> ==> The counter from above that increments 
     <ParentID>5</ParentID> ==> PalletID 
     <Name>test_2</Name> 
    </Line> 
    </Pallet> 
</Result> 

誰能幫助我? 這就是我迄今爲止的內容,但正如您將看到的,palletId的計數器不正確。第二個PalletID應該有ID = 5而不是3:

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

    <xsl:template match="/"> 
    <Result> 
     <xsl:for-each select="root/Pallets/Pallet"> 
     <xsl:variable name="counter" select="1" /> 
     <Pallet> 
      <xsl:variable name="Parentcounter" select="position() + $counter" /> 
      <ID> 
      <xsl:value-of select="$Parentcounter"/> 
      </ID> 
      <ID2>1</ID2> 
      <xsl:for-each select="Line"> 
      <Line> 
       <ID> 
       <xsl:value-of select="$Parentcounter + position()"/> 
       </ID> 
       <ParentID> 
       <xsl:value-of select="$Parentcounter"/> 
       </ParentID> 
       <Name> 
       <xsl:value-of select="Product"/> 
       </Name> 
      </Line> 
      </xsl:for-each> 
     </Pallet> 
     </xsl:for-each> 
    </Result> 
    </xsl:template> 
</xsl:stylesheet> 

在此先感謝。

回答

1

您可以通過簡單地計算托盤元素

<xsl:variable name="id" select="count(preceding::Pallet|preceding::Line) + 2" /> 
<ID><xsl:value-of select="$id" /></ID> 

前的數量。如果你在一個模板匹配通過這個作爲參數得到ID一個托盤元素行元素,然後ID元素將如下(其中$ parentID包含父的ID)

<ID><xsl:value-of select="$ParentID + count(preceding-sibling::Line) + 1" /></ID> 

所以,下面的XSLT應產生所需的輸出

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

    <xsl:template match="Pallets"> 
     <Result> 
     <xsl:apply-templates select="Pallet" /> 
     </Result> 
    </xsl:template> 

    <xsl:template match="Pallet"> 
     <xsl:variable name="id" select="count(preceding::Pallet|preceding::Line) + 2" /> 
     <Pallet> 
     <ID><xsl:value-of select="$id" /></ID> 
     <ID2>1</ID2> 
     <xsl:apply-templates select="Line"> 
      <xsl:with-param name="ParentID" select="$id" /> 
     </xsl:apply-templates> 
     </Pallet> 
    </xsl:template> 

    <xsl:template match="Line"> 
     <xsl:param name="ParentID" /> 
     <Line> 
     <ID><xsl:value-of select="$ParentID + count(preceding-sibling::Line) + 1" /></ID> 
     <ParentID><xsl:value-of select="$ParentID" /></ParentID> 
     <Name><xsl:value-of select="Product" /></Name> 
     </Line> 
    </xsl:template> 
</xsl:stylesheet> 

但是,這不一定是有效的對於較大的托盤和項目的數量,因爲它將不得不重複計數更多的前面的元素(基本上一遍又一遍地計算同一個事物)。另一種方法是利用遞歸模板,每次將Pallet ID的運行總數作爲參數傳遞。試試這個XSLT也:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="Pallets"> 
     <Result> 
     <xsl:apply-templates select="Pallet[1]"/> 
     </Result> 
    </xsl:template> 

    <xsl:template match="Pallet"> 
     <xsl:param name="id" select="2"/> 
     <Pallet> 
     <ID> 
      <xsl:value-of select="$id"/> 
     </ID> 
     <ID2>1</ID2> 
     <xsl:apply-templates select="Line[1]"> 
      <xsl:with-param name="parentID" select="$id"/> 
     </xsl:apply-templates> 
     </Pallet> 
     <xsl:apply-templates select="following-sibling::Pallet[1]"> 
     <xsl:with-param name="id" select="$id + count(Line) + 1"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="Line"> 
     <xsl:param name="parentID"/> 
     <xsl:param name="id" select="$parentID + 1"/> 
     <Line> 
     <ID> 
      <xsl:value-of select="$id"/> 
     </ID> 
     <ParentID> 
      <xsl:value-of select="$parentID"/> 
     </ParentID> 
     <Name> 
      <xsl:value-of select="Product" /> 
     </Name> 
     </Line> 

     <xsl:apply-templates select="following-sibling::Line[1]"> 
     <xsl:with-param name="parentID" select="$parentID"/> 
     <xsl:with-param name="id" select="$id + 1"/> 
     </xsl:apply-templates> 
    </xsl:template> 
</xsl:stylesheet> 

這也產生相同的輸出

<Result> 
    <Pallet> 
     <ID>2</ID> 
     <ID2>1</ID2> 
     <Line> 
     <ID>3</ID> 
     <ParentID>2</ParentID> 
     <Name>test</Name> 
     </Line> 
     <Line> 
     <ID>4</ID> 
     <ParentID>2</ParentID> 
     <Name>test2</Name> 
     </Line> 
    </Pallet> 
    <Pallet> 
     <ID>5</ID> 
     <ID2>1</ID2> 
     <Line> 
     <ID>6</ID> 
     <ParentID>5</ParentID> 
     <Name>test_1</Name> 
     </Line> 
     <Line> 
     <ID>7</ID> 
     <ParentID>5</ParentID> 
     <Name>test_2</Name> 
     </Line> 
    </Pallet> 
</Result> 
+0

謝謝。我用模板的解決方案:) –

0

使用

<xsl:number level="any" count="Pallet|Line"/> 

因爲你是從2日開始,你將不得不把這個變量和添加一個。