2013-08-22 2 views
2

최근에이 질문을했지만 매우 명확하게 설명하지 않았다는 것을 알고 있습니다. 인보이스 당 여러 줄의 큰 .csv 파일 (8000+ 회선)이 있습니다. 아래에 표시된 XML 구조로 구문 분석하고 있습니다 (단순화).XSLT 큰 단일 부모 노드를 더 작은 하위 노드로 분할

입력 1 - $ XMLInput

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-1</invoiceText> 
     <position>1<position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-2</invoiceText> 
     <position>2<position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-1</invoiceText> 
     <position>3<position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-2</invoiceText> 
     <position>4<position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-1</invoiceText> 
     <position>5<position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-2</invoiceText> 
     <position>6<position> 
     ... 
    </row> 
</roow> 

입력 2 - $ maxBatchSize 설명 :이

입력 (일정)이 크기보다 큰 도착 후 다음 배치에 브레이크 3 - $ listOfInvoices에게 설명 : 문서에서 고유 한 송장 번호의 반복 변수. 예 :

<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
    </row> 
</root> 

성능 시간을 개선하려면, 나는 X보다 크지 배치에 INVOICENUMBER하여 이러한 요소 (가져올 변수) 각 노드 그룹에 필요합니다. 거기서 나는 한 번에 전체 원본 문서를 처리하는 대신 각 배치를 하위 프로세서에 병렬로 전송합니다. $ XMLOutput

<root> 
    <batch> 
     <row> 
      <invoiceNumber>1</invoiceNumber> 
      <invoiceText>invoice 1-1</invoiceText> 
      <position>1<position> 
      ... 
     </row> 
     <row> 
      <invoiceNumber>1</invoiceNumber> 
      <invoiceText>invoice 1-2</invoiceText> 
      <position>2<position> 
      ... 
     </row> 
     <row> 
      <invoiceNumber>2</invoiceNumber> 
      <invoiceText>invoice 2-1</invoiceText> 
      <position>3<position> 
      ... 
     </row> 
     <row> 
      <invoiceNumber>2</invoiceNumber> 
      <invoiceText>invoice 2-2</invoiceText> 
      <position>4<position> 
      ... 
     </row> 
    </batch> 
    <batch> 
     <row> 
      <invoiceNumber>3</invoiceNumber> 
      <invoiceText>invoice 3-1</invoiceText> 
      <position>5<position> 
      ... 
     </row> 
     <row> 
      <invoiceNumber>3</invoiceNumber> 
      <invoiceText>invoice 3-2</invoiceText> 
      <position>6<position> 
      ... 
     </row> 
    </batch> 
</root> 

그것은 모든 요구 사항입니다 -

출력 1 : 예를 들면, 위의 예제 XML의 문서에서, 배치 크기는 나는 다음과 같은 XML 출력을 필요, 3보다 큰있을 수 있다면 송장의 행은 동일한 배치로 보내집니다. 내 초기 XSLT 시도가 아래 (2.0)이며, while 루프를 에뮬레이트하려고 시도하고 템플릿을 재귀 적으로 호출하여 현재 노드에 송장 그룹을 계속 추가합니다. 최대 일괄 처리 크기에 도달하면 재귀 적으로 일괄 처리 템플릿을 호출하여 새 일괄 처리를 만듭니다. 각 순환 호출간에 송장 및 배치 카운터를 전달합니다.

편집 : Ken의 도움 덕분에 더 가까워지고 있습니다. 개별 송장 수가 아닌 매번 회선 수별로 송장을 분할해야합니다. 이론적으로 아래의 내용이 작동하는 경우 인보이스 번호가 선행 형제 노드에 존재하지 않는지 확인하는 방법이 확실하지 않습니다.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<xsl:variable name="batch-size" select="40" as="xs:integer"/> 
<xsl:variable name="input" select="bpws:getVariableData('sortedInvoicesByBU')"/> 
<xsl:key name="invoice-lines-by-invoice-number" match="row" use="invoiceNumber4z"/> 

<xsl:template match="/"> 
    <xsl:element name="batches"> 
     <!--establish batches from possible non-contiguous invoice numbers--> 
     <xsl:for-each-group select="$input/*:UPSData/*:row" group-by="(position() - 1) idiv $batch-size"> 
      <xsl:for-each select="distinct-values($input/*:UPSData/*:row/*:invoiceNumber4z)[not(.=preceding-sibling::item)]"> 
       <xsl:element name="UPSData"> 
        <xsl:for-each select="current()"> 
         <xsl:for-each select="key('invoice-lines-by-invoice-number',.,$input)"> 
          <!--copy rows as they are--> 
          <xsl:copy-of select="."/> 
         </xsl:for-each> 
        </xsl:for-each> 
       </xsl:element> 
      </xsl:for-each> 
     </xsl:for-each-group> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 

답변

4

나는 하나가 마침내 일을 얻기 위해 필요한만큼 스타일 시트를 고문 할 수 학생들에게,하지만 그것을 유지 관리하거나 일을하는 경우에도 올바른 방법으로하지 않습니다. XSLT를 명령형 언어로 취급한다는 분석을 받아 들일 수 있기를 바랍니다. 언어는 정의가 없으며 C와 Java에서 더 쉽고 쉬운 일을 시도하는 것이 어렵고 장황하고 어색하다는 것을 당신에게 확신시킬 것입니다 .

그러나 XSLT를 사용하여 작업하면 명령형 언어보다 쉬워지고 부팅하는 것은 모두 원하는 결과를 나타내는 XML을 기반으로합니다. 그것이 더 짧기 때문에, 유지하기가 더 쉽습니다. 사용되는 선언적 명령어를 이해하면 명령형 알고리즘을 시도하거나 해체 할 필요가 없습니다. 또한 XSLT 프로세서는 선언적 접근 방식을 최적화 할 수 있지만 최적화 된 기회가 없으면 서면 접근 방식을 따르는 경우 느리게 작동해야합니다.

아래 솔루션에서는 Output1 결과를 정확히 산출합니다. 고유 송장 번호를 결정한 다음 올바른 값으로 필터링하는 방법에 유의하십시오. 그런 다음 일괄 처리 크기 (매개 변수)를 기준으로 배치합니다. 템플릿이 필요없고 어떤 종류의 카운터도 필요하지 않습니다 ... XSLT 2.0의 기본 제공 기능을 사용하는 솔루션입니다.<root>, <xsl:for-each-group>, <batch>, <xsl:for-each><xsl:copy-of> : 글로벌 매개 변수와 변수와 주석의 선언을 포함

그리고하지, 그것은 긴 5 요소입니다.

당신의 질문에 대해서는 당신이 왜 효과가 없는지 모르지만 ... 당신이 취한 접근 방식은 XSLT처럼 "느껴지지"않습니다 ... 그것은 프로그래밍 방식의 접근 방식에 대한 XSLT 표현처럼 느낍니다. 난 당신이 상태 때문에 아래의 대안을 추가하려면이 대답을 편집하고있어

t:\ftemp>type numbers.xml 
<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
    </row> 
</root> 

t:\ftemp>type invoices.xml 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-1</invoiceText> 
     <position>1</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-2</invoiceText> 
     <position>2</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-1</invoiceText> 
     <position>3</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-2</invoiceText> 
     <position>4</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-1</invoiceText> 
     <position>5</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-2</invoiceText> 
     <position>6</position> 
     ... 
    </row> 
</root> 

t:\ftemp>call xslt2 invoices.xml invoices.xsl 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <batch> 
     <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-1</invoiceText> 
     <position>1</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-2</invoiceText> 
     <position>2</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-1</invoiceText> 
     <position>3</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-2</invoiceText> 
     <position>4</position> 
     ... 
    </row> 
    </batch> 
    <batch> 
     <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-1</invoiceText> 
     <position>5</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-2</invoiceText> 
     <position>6</position> 
     ... 
    </row> 
    </batch> 
</root> 

t:\ftemp>type invoices.xsl 
<?xml version="1.0" encoding="US-ASCII"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="2.0"> 

<xsl:output indent="yes"/> 

<xsl:param name="batch-size" select="2"/> 

<xsl:variable name="valid-numbers" 
       select="doc('numbers.xml')/root/row/invoiceNumber"/> 

<xsl:template match="/"> 
    <xsl:variable name="invoiceLines" select="root/row"/> 
    <root> 
    <!--establish batches from possible non-contiguous invoice numbers--> 
    <xsl:for-each-group group-by="(position() - 1) idiv $batch-size" 
     select="distinct-values($invoiceLines/invoiceNumber)[.=$valid-numbers]"> 
     <!--create a batch using all invoice lines for all numbers in group--> 
     <batch> 
     <xsl:for-each select="$invoiceLines[invoiceNumber=current-group()]"> 
      <!--copy rows as they are--> 
      <xsl:copy-of select="."/> 
     </xsl:for-each> 
     </batch> 
    </xsl:for-each-group> 
    </root> 
</xsl:template> 

</xsl:stylesheet> 
t:\ftemp>rem Done! 

당신은 내 간단한 변수 조건보다 더 나은 수행하는 것 키 조회 테이블을 사용하여 생각 8000000 개 입력 기록을 가지고있다. 템플릿에 하나의 추가 XSLT 명령을 사용하여 동일한 결과를 생성합니다 (추가하지 않고도이 작업을 수행 할 수 있지만 읽기 쉽다는 느낌이 들었습니다). 그리고 더 이상 필요하지 않은 변수를 제거합니다.

<?xml version="1.0" encoding="US-ASCII"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="2.0"> 

<xsl:output indent="yes"/> 

<xsl:param name="batch-size" select="2"/> 

<xsl:variable name="valid-numbers" 
       select="doc('numbers.xml')/root/row/invoiceNumber"/> 

<xsl:key name="invoice-lines-by-invoice-number" 
     match="row" use="invoiceNumber"/> 

<xsl:variable name="input" select="/"/> 

<xsl:template match="/"> 
    <root> 
    <!--establish batches from possible non-contiguous invoice numbers--> 
    <xsl:for-each-group group-by="(position() - 1) idiv $batch-size" 
     select="distinct-values(root/row/invoiceNumber)[.=$valid-numbers]"> 
     <!--create a batch using all invoice lines for all numbers in group--> 
     <batch> 
     <xsl:for-each select="current-group()"> 
      <xsl:for-each 
        select="key('invoice-lines-by-invoice-number',.,$input)"> 
      <!--copy rows as they are--> 
      <xsl:copy-of select="."/> 
      </xsl:for-each> 
     </xsl:for-each> 
     </batch> 
    </xsl:for-each-group> 
    </root> 
</xsl:template> 

</xsl:stylesheet> 
+0

다시 감사합니다. 나는 프로그래밍 방식으로 XSLT를 적절하게 적용하려고 노력하고 있었고, 기능적 언어로 생각하는 법을 배우기 시작했습니다. 시도한 프로그래밍 방식이 효과가없는 이유는 그것이 설계된 방식이 아니기 때문입니다. – rwolters3

+0

당신이 도왔던 두 가지 질문이 내 책을 다운로드하고 공부하고, 내 영역에 강의/수업이 있는지, 이전 강좌의 캐시 된 버전인지를 확인하는 것이 좋을 것 같습니다. :) 또한 내가 만든 작은 오타가 있었는데, 나는 8000 또는 8k 레코드가 아니라 800 만, 훨씬 더 빠른 처리 시간을 말하고자했습니다. – rwolters3

+0

내 StackOverflow 프로필을 곧 다가올 강의 시리즈로 업데이트하거나 http://www.CraneSoftwrights.com/schedule.htm#calendar에 정보가 있습니다. 그리고 http://www.CraneSoftwrights.com/links/udemy-ptux-online.htm에서 XSLT/XPath에 5 시간 분량의 무료 스트리밍 비디오 강좌가 있습니다. 사용자 이름을 설정하지 않아도됩니다. 그냥 자유롭게 보아라. Udemy는 http://www.CraneSoftwrights.com/training/ptux/ptux-video.htm 페이지를 통해 구입할 수있는 DVD 스트리밍 버전을 호스팅합니다. 둘 다 완전한 답을 가진 연습 문제가 있습니다. 독립 실행 형 서적에는 연습 문제가 없습니다. –

0

이전 답은 원래 질문에 대한 답변이므로이 답을 표시하지 마십시오.

아래 코드는 두 배치 간의 송장을 깨지 않고 송장에 걸린 총 줄 수를 일괄 처리하는 방법에 대한 부수적 인 질문에 대한 답변입니다.

선언적으로 수행하는 방법을 설명 할 수 없으므로 아래의 답은 긴급 재귀 솔루션이지만 꼬리 재귀를 구현하는 XSLT 프로세서가 스택 공간을 차지하지 않도록 작성했습니다. 또한 다른 언어로 모방하기에 어색한 네이티브 XSLT 기능 (키 테이블 및 시퀀스)을 활용합니다.

코드가 실제로 단 한 구역 만 인보이스를 작성하므로 코드가 빡빡합니다. 더 이상 일괄 쓰기 코드 블록이 없습니다. 나는 이것이 어떻게 밝혀 졌는지에 만족한다.

개선점이나 이에 대한 대안 솔루션의 게시물 제안을 환영합니다.

t:\ftemp>type numbers.xml 
<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
    </row> 
    <row> 
     <invoiceNumber>5</invoiceNumber> 
    </row> 
</root> 

t:\ftemp>type invoices.xml 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-1</invoiceText> 
     <position>1</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-2</invoiceText> 
     <position>2</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-1</invoiceText> 
     <position>3</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-2</invoiceText> 
     <position>4</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-1</invoiceText> 
     <position>5</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-2</invoiceText> 
     <position>6</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-1</invoiceText> 
     <position>7</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-2</invoiceText> 
     <position>8</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-3</invoiceText> 
     <position>9</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-4</invoiceText> 
     <position>10</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-5</invoiceText> 
     <position>11</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-6</invoiceText> 
     <position>12</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>5</invoiceNumber> 
     <invoiceText>invoice 5-1</invoiceText> 
     <position>13</position> 
     ... 
    </row> 
    <row> 
     <invoiceNumber>5</invoiceNumber> 
     <invoiceText>invoice 5-2</invoiceText> 
     <position>14</position> 
     ... 
    </row> 
</root> 

t:\ftemp>call xslt2 invoices.xml invoices.xsl 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <!--Batch max lines: 5--> 
    <batch> 
    <!--invoice numbers: 1 2--> 
    <!--total line count: 4--> 
    <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-1</invoiceText> 
     <position>1</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>1</invoiceNumber> 
     <invoiceText>invoice 1-2</invoiceText> 
     <position>2</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-1</invoiceText> 
     <position>3</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>2</invoiceNumber> 
     <invoiceText>invoice 2-2</invoiceText> 
     <position>4</position> 
     ... 
    </row> 
    </batch> 
    <batch> 
    <!--invoice numbers: 3--> 
    <!--total line count: 2--> 
    <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-1</invoiceText> 
     <position>5</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>3</invoiceNumber> 
     <invoiceText>invoice 3-2</invoiceText> 
     <position>6</position> 
     ... 
    </row> 
    </batch> 
    <batch> 
    <!--invoice numbers: 4--> 
    <!--total line count: 6--> 
    <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-1</invoiceText> 
     <position>7</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-2</invoiceText> 
     <position>8</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-3</invoiceText> 
     <position>9</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-4</invoiceText> 
     <position>10</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-5</invoiceText> 
     <position>11</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>4</invoiceNumber> 
     <invoiceText>invoice 4-6</invoiceText> 
     <position>12</position> 
     ... 
    </row> 
    </batch> 
    <batch> 
    <!--invoice numbers: 5--> 
    <!--total line count: 2--> 
    <row> 
     <invoiceNumber>5</invoiceNumber> 
     <invoiceText>invoice 5-1</invoiceText> 
     <position>13</position> 
     ... 
    </row> 
     <row> 
     <invoiceNumber>5</invoiceNumber> 
     <invoiceText>invoice 5-2</invoiceText> 
     <position>14</position> 
     ... 
    </row> 
    </batch> 
</root> 

t:\ftemp>type invoices.xsl 
<?xml version="1.0" encoding="US-ASCII"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="2.0"> 

<xsl:output indent="yes"/> 

<xsl:param name="batch-size" select="5"/> 

<xsl:variable name="valid-numbers" 
       select="doc('numbers.xml')/root/row/invoiceNumber"/> 

<xsl:key name="invoice-lines-by-invoice-number" 
     match="row" use="invoiceNumber"/> 

<xsl:variable name="input" select="/"/> 

<xsl:template match="/"> 
    <root> 
    <xsl:text>&#xa; </xsl:text> 
    <xsl:comment select="'Batch max lines:',$batch-size"/> 
    <xsl:text>&#xa; </xsl:text> 
    <xsl:call-template name="next-batch"> 
     <xsl:with-param name="remaining-numbers" 
     select="distinct-values(root/row/invoiceNumber)[.=$valid-numbers]"/> 
    </xsl:call-template> 
    </root> 
</xsl:template> 

<xsl:template name="next-batch"> 
    <xsl:param name="this-batch-lines" select="0"/> 
    <xsl:param name="this-batch-numbers" select="()"/> 
    <xsl:param name="remaining-numbers" required="yes"/> 
    <xsl:variable name="this-invoice" select="$remaining-numbers[1]"/> 
    <xsl:variable name="this-invoice-lines" 
    select="count(key('invoice-lines-by-invoice-number',$this-invoice,$input))"/> 

    <xsl:choose> 
    <xsl:when test="not($this-invoice) and not($this-batch-lines)"> 
     <!--nothing to clean up and nothing more to do--> 
    </xsl:when> 
    <xsl:when test="not($this-invoice) (:last invoice complete:) or 
        ($this-batch-lines + $this-invoice-lines > $batch-size) 
         (:this invoice exceeds limit:)"> 
     <!--clean up previous unfinished batch--> 
     <batch> 
     <xsl:text>&#xa; </xsl:text> 
     <xsl:comment select="'invoice numbers:',$this-batch-numbers"/> 
     <xsl:text>&#xa; </xsl:text> 
     <xsl:comment select="'total line count:',$this-batch-lines"/> 
     <xsl:text>&#xa; </xsl:text> 
     <xsl:copy-of select="for $num in $this-batch-numbers return 
         key('invoice-lines-by-invoice-number',$num,$input)"/> 
     </batch> 
     <xsl:if test="$this-invoice"> 
     <!--continue with the next batch comprised of this invoice only--> 
     <xsl:call-template name="next-batch"> 
      <xsl:with-param name="this-batch-lines" 
          select="$this-invoice-lines"/> 
      <xsl:with-param name="this-batch-numbers" 
          select="$this-invoice"/> 
      <xsl:with-param name="remaining-numbers" 
          select="$remaining-numbers[position()>1]"/> 
     </xsl:call-template> 
     </xsl:if> 
     <!--the cleaned up batch was the last batch, template recursion ends--> 
    </xsl:when> 
    <xsl:otherwise> 
     <!--a batch limit has not been exceeded; add this invoice to batch--> 
     <xsl:call-template name="next-batch"> 
     <xsl:with-param name="this-batch-lines" 
         select="$this-batch-lines + $this-invoice-lines"/> 
     <xsl:with-param name="this-batch-numbers" 
         select="($this-batch-numbers,$this-invoice)"/> 
     <xsl:with-param name="remaining-numbers" 
          select="$remaining-numbers[position()>1]"/> 
     </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 
관련 문제