2014-09-24 51 views
0

制作一个表我有下面的XML。从段落

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
<para align="center">BETWEEN</para> 
<para columns="1">Column1 data</para> 
<para columns="1">Column1 data</para> 
<para columns="1">Column1 data</para> 
<para columns="2">Column2 data</para> 
<para columns="3">Column3 data</para> 
<para align="center">AND</para> 
<para columns="1">Column1 data</para> 
<para columns="1">Column1 data</para> 
<para columns="1">Column1 data</para> 
<para columns="2">Column2 data</para> 
<para columns="3">Column3 data</para> 
<para columns="2">Column2 data</para> 
<para columns="2">Column2 data</para> 
<para columns="2">Column2 data</para> 
<para columns="2">Column2 data</para> 
<para columns="2">Column2 data</para> 
<para columns="2">Column2 data</para> 
<para align="center">Between</para> 
<para align="center">____________________</para> 
</root> 

这里实际上我想将para转换成表列,因为我试过了XSLT。但问题在于,每个段落都有一个新表格。

这里的columns属性状态,在哪个列中,数据是否属于,如果columns="1"这意味着只有一行和一列。如果是columns="2",则说明数据属于第2列内容的同一行,如果前面有columns="1",则同一行的第1列应该有内容,否则第1列应留空。

,我试过的代码可以发现here

预期输出是

<table> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td>Column 2 data</td> 
      <td>Column 3 data</td> 
     </tr> 
    </table> 
    <div class="para align-center">AND</div> 
    <table> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td>Column 2 data</td> 
      <td>Column 3 data</td> 
     </tr> 
    </table> 
    <table> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td></td> 
      <td></td> 
     </tr> 
     <tr> 
      <td>Column1 data</td> 
      <td>Column 2 data</td> 
      <td>Column 3 data</td> 
     </tr> 
    </table> 

    <table> 
     <tr> 
      <td></td> 
      <td>Column2 data</td> 
      <td></td> 
     </tr> 
     <tr> 
      <td></td> 
      <td>Column 2 data</td> 
      <td></td> 
     </tr> 
     <tr> 
      <td></td> 
      <td>Column 2 data</td> 
      <td></td> 
     </tr> 
     <tr> 
      <td></td> 
      <td>Column2 data</td> 
      <td></td> 
     </tr> 
     <tr> 
      <td></td> 
      <td>Column 2 data</td> 
      <td></td> 
     </tr> 
     <tr> 
      <td></td> 
      <td>Column 2 data</td> 
      <td></td> 
     </tr> 
    </table> 
    <div class="para align-center">BETWEEN</div> 

请让我知道我可以解决这个问题。

谢谢。

回答

1

如果您真正使用XSLT 2.0(链接示例中的处理器为2.0处理器,但XSLT @version为1.0),则应该可以使用xsl:for-each-group。您可以将para元素分组到表中,然后将它们分组到这些表内的行中。

可能有更好的方法来做到这一点,但我只有几分钟的时间来尝试一些东西。希望这足以让你开始。

XML输入(用于测试略有修改)

<root> 
    <para align="center">BETWEEN</para> 
    <para columns="1">Column1 data</para> 
    <para columns="1">Column1 data</para> 
    <para columns="1">Column1 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="3">Column3 data</para> 
    <para align="center">AND</para> 
    <para columns="1">Column1 data</para> 
    <para columns="1">Column1 data</para> 
    <para columns="1">Column1 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="3">Column3 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="2">Column2 data</para> 
    <para columns="2">Column2 data</para> 
    <!--Added for testing--> 
    <para columns="1">Column1 data</para> 
    <para columns="3">Column3 data</para> 
    <!--=================--> 
    <para align="center">Between</para> 
    <para align="center">____________________</para> 
</root> 

XSLT 2.0

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs"> 
    <xsl:output indent="yes" method="html"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="max-cols" select="max(/*/para/@columns)"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/*"> 
     <xsl:for-each-group select="para" group-ending-with="para[@columns][@columns > following-sibling::para[@columns][1]/@columns]"> 
      <xsl:apply-templates select="current-group()[not(@columns)][following-sibling::para[generate-id()=generate-id((current-group()[@columns])[1])]]"/> 
      <table> 
       <xsl:for-each-group select="current-group()[@columns]" group-starting-with="para[preceding-sibling::para[1]/@columns >= @columns]"> 
        <tr> 
         <xsl:call-template name="empty-cols"> 
          <xsl:with-param name="col-cnt" select="xs:integer(current-group()[position()=1]/@columns - 1)"/> 
         </xsl:call-template> 
         <xsl:apply-templates select="current-group()"/> 
         <xsl:call-template name="empty-cols"> 
          <xsl:with-param name="col-cnt" select="xs:integer($max-cols - current-group()[last()]/@columns)"/> 
         </xsl:call-template> 
        </tr>       
       </xsl:for-each-group> 
      </table> 
      <xsl:apply-templates select="current-group()[not(@columns)][preceding-sibling::para[generate-id()=generate-id((current-group()[@columns])[last()])]]"/>       
     </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template name="empty-cols"> 
     <xsl:param name="col-cnt" as="xs:integer"/> 
     <xsl:for-each select="1 to $col-cnt"> 
      <td/> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="para[not(@columns)]"> 
     <div class="para{if (string(@align)) then concat(' align-',@align) else ''}"> 
      <xsl:apply-templates/> 
     </div> 
    </xsl:template> 

    <xsl:template match="para[@columns]"> 
     <xsl:call-template name="empty-cols"> 
      <xsl:with-param name="col-cnt" select="if (preceding-sibling::para[1][@columns][current()/@columns >= @columns - 1]) then xs:integer((@columns - 1) - preceding-sibling::para[1][@columns]/@columns) else xs:integer(0)"/> 
     </xsl:call-template>   
     <td> 
      <xsl:apply-templates/> 
     </td> 
    </xsl:template> 

</xsl:stylesheet> 

输出

<div class="para align-center">BETWEEN</div> 
<table> 
    <tr> 
     <td>Column1 data</td> 
     <td></td> 
     <td></td> 
    </tr> 
    <tr> 
     <td>Column1 data</td> 
     <td></td> 
     <td></td> 
    </tr> 
    <tr> 
     <td>Column1 data</td> 
     <td>Column2 data</td> 
     <td>Column3 data</td> 
    </tr> 
</table> 
<div class="para align-center">AND</div> 
<table> 
    <tr> 
     <td>Column1 data</td> 
     <td></td> 
     <td></td> 
    </tr> 
    <tr> 
     <td>Column1 data</td> 
     <td></td> 
     <td></td> 
    </tr> 
    <tr> 
     <td>Column1 data</td> 
     <td>Column2 data</td> 
     <td>Column3 data</td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>Column2 data</td> 
     <td></td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td>Column1 data</td> 
     <td></td> 
     <td>Column3 data</td> 
    </tr> 
</table> 
<div class="para align-center">Between</div> 
<div class="para align-center">____________________</div>