2014-02-15 57 views
0

我想從包含多個標題行的文件創建一組xml,後面是每個標題的多個詳細信息行。XSL頭和細節分組

這裏是原始XML的示例:

編輯:隨後的報頭片材將發生變化詳細的張數。所以,Sheet [4]/FIELD1將不總是具有Header的值。此外,該文件將始終有一個或多個頁眉表。表格是行。

編輯:XSLT-1.0

<Root> 
    <Sheet> 
     <FIELD1>Header</FIELD1> 
     <FIELD2>Value1</FIELD2> 
     <FIELD3>Value2</FIELD3> 
    </Sheet> 
    <Sheet> 
     <FIELD1>Detail</FIELD1> 
     <FIELD2>Value3</FIELD2> 
     <FIELD3>Value4</FIELD3> 
     </Sheet> 
    <Sheet> 
      <FIELD1>Detail</FIELD1> 
      <FIELD2>Value5</FIELD2> 
      <FIELD3>Value6</FIELD3> 
     </Sheet> 
    <Sheet> 
      <FIELD1>Header</FIELD1> 
      <FIELD2>Value7</FIELD2> 
      <FIELD3>Value8</FIELD3> 
     </Sheet> 
    <Sheet> 
      <FIELD1>Detail</FIELD1> 
      <FIELD2>Value9</FIELD2> 
      <FIELD3>Value10</FIELD3> 
     </Sheet> 
    <Sheet> 
      <FIELD1>Detail</FIELD1> 
      <FIELD2>Value11</FIELD2> 
      <FIELD3>Value12</FIELD3> 
     </Sheet> 
    <Sheet> 
      <FIELD1>Detail</FIELD1> 
      <FIELD2>Value13</FIELD2> 
      <FIELD3>Value14</FIELD3> 
    </Sheet> 
</Root> 

這裏是輸出應類似於什麼:

編輯:發票的數量將通過頭片材(行)的數目來確定。 LineItem行將與Header後面的Detail表相同。

<Root> 
    <Invoice AttribOne="Value1" AttribTwo="Value2" > 
     <LineItem LIAttribOne="Value3" LIAttribTwo="Value4"/> 
     <LineItem LIAttribOne="Value5" LIAttribTwo="Value6"/> 
    </Invoice> 
    <Invoice AttribOne="Value7" AttribTwo="Value8" > 
     <LineItem LIAttribOne="Value9" LIAttribTwo="Value10"/> 
     <LineItem LIAttribOne="Value11" LIAttribTwo="Value12"/> 
     <LineItem LIAttribOne="Value13" LIAttribTwo="Value14"/> 
    </Invoice> 
</Root> 

編輯:如下回答:

+0

確定。如何標識標題字段?或細節字段? 「標題」和「細節」這兩個詞是否有意義? – helderdarocha

+0

Sheet/FIELD1將始終具有「標題」或「詳細信息」的值。表格之間沒有其他區別。 – Alsace

回答

0

我曾這一點,並添加以下代碼註釋來形容了。

下面是解:

<xsl:template match="/Root"> 
    <Root> 
     <xsl:apply-templates select="Sheet[FIELD1 = 'Header']" /> 
    </Root> 
</xsl:template> 

<xsl:template match="Sheet[FIELD1 = 'Detail']" > 
    <LineItem> 
     <xsl:attribute name="LIAttribOne" > 
     <xsl:value-of select="FIELD2"/> 
     </xsl:attribute> 
     <xsl:attribute name="LIAttribTwo" > 
     <xsl:value-of select="FIELD3"/> 
     </xsl:attribute> 
    </LineItem> 
</xsl:template> 

<xsl:template match="Sheet[FIELD1 = 'Header']"> 
    <Invoice> 
     <xsl:attribute name="AttribOne" > 
     <xsl:value-of select="FIELD2"/> 
     </xsl:attribute> 
     <xsl:attribute name="AttribTwo" > 
     <xsl:value-of select="FIELD3"/> 
     </xsl:attribute> 
    <!-- Get the count of all details the previous headers contained --> 
    <xsl:variable name="prevCnt" select="count(preceding-sibling::*[FIELD1 = 'Detail'])"/> 
    <!-- Get the count of all details in the previous headers and this header contain --> 
    <xsl:variable name="newCnt" select="count(following-sibling::*[FIELD1 = 'Header'][1]/preceding-sibling::*[FIELD1 = 'Detail'])"/> 
    <!-- This will return a 1 if there is a following header, else 0 --> 
    <xsl:variable name="pos" select="count(following-sibling::*[FIELD1 = 'Header'][1])" /> 
    <!-- select every detail whose position is less than $newCnt - $preCnt or all if there is no following header --> 
    <xsl:apply-templates select="following-sibling::*[FIELD1 = 'Detail'][position() &lt; ($newCnt - $prevCnt + 1) or $pos = 0]" /> 
</Invoice> 

0

試試這個:

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

    <xsl:template match="Root"> 
     <xsl:copy> 
      <Invoice AttribOne="{Sheet[1]/FIELD2}" AttribTwo="{Sheet[1]/FIELD3}"> 
       <xsl:apply-templates select="Sheet[2] | Sheet[3]"/> 
      </Invoice> 
      <Invoice AttribOne="{Sheet[4]/FIELD2}" AttribTwo="{Sheet[4]/FIELD3}"> 
       <xsl:apply-templates select="Sheet[5] | Sheet[6] | Sheet[7]"/> 
      </Invoice> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Sheet"> 
     <LineItem LIAttribOne="{FIELD2}" LIAttribTwo="{FIELD3}"/> 
    </xsl:template> 

</xsl:stylesheet> 
+0

感謝您的回覆。這是行不通的,因爲哪個表具有Header值(雖然[1]當然會),並且其中Detail值會因文件而異。 – Alsace

+0

這會生成上面發佈的內容。你有沒有提到其他的要求? – helderdarocha

+0

您可以通過'/ Root/Sheet [1]/FIELD1'和'/ Root/Sheet [4]/FIELD1'獲取Header值,並在另一個'/ Root/Sheet [n]/FIELD1' 。 – helderdarocha