2017-08-31 17 views
0

我正在使用XSLT转换生成XML文档,该文档在创建后会被拆分以生成多个文件。最后文件的一般结构如下所示:XSLT 1.0 - 每个文件的记录数有限

<DOC> 
    <NEWFILE/> 
    <REALROOT> 
     <SENDER></SENDER> 
     <INVOICE> 
      <IVC_ID></IVS_ID> 
      <LINEITEM></LINEITEM> 
      <LINEITEM></LINEITEM> 
      ... 
     </INVOICE> 
     <INVOICE> 
      <IVC_ID></IVS_ID> 
      <LINEITEM></LINEITEM> 
      <LINEITEM></LINEITEM> 
      ... 
     </INVOICE> 
     ... 
    </REALROOT> 

    <NEWFILE/> 

    <REALROOT> 
     <SENDER></SENDER> 
     <INVOICE> 
      <IVC_ID></IVS_ID> 
      <LINEITEM></LINEITEM> 
      <LINEITEM></LINEITEM> 
      ... 
     </INVOICE> 
     <INVOICE> 
      <IVC_ID></IVS_ID> 
      <LINEITEM></LINEITEM> 
      <LINEITEM></LINEITEM> 
      ... 
     </INVOICE> 
     ... 
    </REALROOT> 
    <NEWFILE/> 
</DOC> 

DOC<NEWFILE/>标签是终端产品的界限,但是这不是问题的问题。

在输出到上述结构之前,我的输入数据需要通过发件人和发票进行分组,并且我已经设法做到了这一点,但是我还想限制每个文件的发票数量并且无法找到一种方法来做到这一点。

我的输入数据被细分为订单项级别,像这样:

<ROOT> 
    <DATA> 
     <SNDR>1</SNDR> 
     <INVOICE>1</INVOICE> 
     <LINEITEM>1</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>1</SNDR> 
     <INVOICE>1</INVOICE> 
     <LINEITEM>2</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>1</SNDR> 
     <INVOICE>2</INVOICE> 
     <LINEITEM>1</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>1</SNDR> 
     <INVOICE>3</INVOICE> 
     <LINEITEM>1</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>1</SNDR> 
     <INVOICE>3</INVOICE> 
     <LINEITEM>2</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>2</SNDR> 
     <INVOICE>1</INVOICE> 
     <LINEITEM>1</LINEITEM> 
    </DATA> 
    <DATA> 
     <SNDR>2</SNDR> 
     <INVOICE>2</INVOICE> 
     <LINEITEM>1</LINEITEM> 
    </DATA> 
</ROOT> 

如果我把它限制在每个文件2张发票,我希望这样的输出:

<DOC> 
    <REALROOT> 
     <SENDER>1</SENDER> 
     <INVOICE> 
      <IVC_ID>1</IVS_ID> 
      <LINEITEM>1</LINEITEM> 
      <LINEITEM>2</LINEITEM> 
     </INVOICE> 
     <INVOICE> 
      <IVC_ID>2</IVS_ID> 
      <LINEITEM>1</LINEITEM> 
     </INVOICE> 
    </REALROOT> 

    <NEWFILE/> 

    <REALROOT> 
     <SENDER>1</SENDER> 
     <INVOICE> 
      <IVC_ID>3</IVS_ID> 
      <LINEITEM>1</LINEITEM> 
      <LINEITEM>2</LINEITEM> 
     </INVOICE> 
    </REALROOT> 

    <NEWFILE/> 

    <REALROOT> 
     <SENDER>2</SENDER> 
     <INVOICE> 
      <IVC_ID>1</IVS_ID> 
      <LINEITEM>1</LINEITEM> 
     </INVOICE> 
     <INVOICE> 
      <IVC_ID>2</IVS_ID> 
      <LINEITEM>1</LINEITEM> 
     </INVOICE> 
    </REALROOT> 
</DOC> 

这里我到目前为止。这使我可以按发件人和发票分组,但我无法弄清楚如何处理发票数量限制。

+0

您无法对尚不存在的内容进行分组。您需要两次完成此操作:首先将项目分组为发票,然后将发票分组为文件。 –

+0

XSLT是图灵完整的。如果您可以使用编程语言生成输出,则可以使用XSLT生成输出。试图成为一个不同的问题是否是理智的。 – kumesana

回答

0

首先,对于每个发件人,您需要发件人的所有发票清单。

这就是你对前两个foreach所做的,但我说你需要一个列表。所以第二个,不必是一个习惯。把它们放在一个变量中:

<xsl:variable name="invoicesWithThisSender" 
        select="key('data-by-SNDR', current()/SNDR)[not(INVOICE = preceding-sibling::DATA[1]/INVOICE)]" /> 

这是相同的选择,在一个变量,而不是for-each。

现在,您需要将所有这些列表中的元素写入所需的文件中。

由于XSLT 1.0不提供分区机制,我知道这样做的唯一方法是通过调用递归命名模板。

试试这个:

<xsl:template name="writeFilesForSender"> 
    <xsl:param name="invoicesWithThisSender" /> 

    <xsl:if test="$invoicesWithThisSender"> 
     <NEWFILE /> 

     <REALROOT> 
      <SNDR> 
       <xsl:value-of select="SNDR" /> 
      </SNDR> 
      <xsl:for-each select="$invoicesWithThisSender[position() &lt;= 2]"> 
       <INVOICE> 
        <IVC_ID> 
         <xsl:value-of select="INVOICE" /> 
        </IVC_ID> 
       </INVOICE> 
      </xsl:for-each> 
     </REALROOT> 

     <xsl:call-template name="writeFilesForSender"> 
      <xsl:with-param name="invoicesWithThisSender" 
       select="$invoicesWithThisSender[position() > 2]" /> 
     </xsl:call-template> 
    </xsl:if> 

</xsl:template> 

与此调用它:

<xsl:call-template name="writeFilesForSender"> 
    <xsl:with-param name="invoicesWithThisSender" 
     select="$invoicesWithThisSender" /> 
</xsl:call-template> 

从我的理解和我的测试,你的问题就解决了。

+0

https://stackoverflow.com/questions/45968516/simple-xsl-issue-with-if-statement-inside-for-each/45968983#45968983 –

+0

@ michael.hor257k没错,好多了。我认为这是值得自己回答的。 – kumesana