2014-02-15 60 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