2011-05-03 41 views
3

更新改寫問題以澄清混淆。
XSLT - 生產地址標籤

我正在使用XSLT和XSL:由Apache FOP翻譯的FO。我想打印地址標籤。

INPUT

<?xml version="1.0" encoding="utf-8" ?> 
<workOrders> 
    <workOrder> 
    <number>111</number> 
    <PartNumber>110022</PartNumber> 
    <col3>222</col3> 
    <Qty>333</Qty> 
    </workOrder> 
    <workOrder> 
    <number>111</number> 
    <PartNumber>110022</PartNumber> 
    <col3>222</col3> 
    <Qty>333</Qty> 
    </workOrder> 

    <!--Manually copy/paste the workOrder until you have 47 of them..--> 
</workOrders> 

OUTPUT
第1頁(整頁6行×3個COLS)
Page1

頁2是相同第1

頁3(部分頁面...在這種情況下4行x 3列和l AST項目空白)

Page3


UPDATE2
我插上亞歷杭德羅的解決方案。我得到說

XSL被Apache FOP報告錯誤:模板是不是在這個位置允許在樣式表

下面是來自HTML的東西到XSL轉換的代碼:FO。錯誤點由評論標記。我搞砸了什麼?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> 

    <fo:layout-master-set> 

     <!-- layout for the first page --> 
     <fo:simple-page-master master-name="first" 
      page-height="11in" 
      page-width="8.5in" 
      margin-top="1cm" 
      margin-bottom="1cm" 
      margin-left="1cm" 
      margin-right="1cm"> 
     <fo:region-body margin-top="0cm"/> 
     <fo:region-before extent="1cm"/> 
     <fo:region-after extent="0cm"/> 
     </fo:simple-page-master> 

     <!-- layout for the other pages --> 
     <fo:simple-page-master master-name="rest" 
      page-height="11in" 
      page-width="8.5in" 
      margin-top="1cm" 
      margin-bottom="1cm" 
      margin-left="1cm" 
      margin-right="1cm"> 
     <fo:region-body margin-top="0cm"/> 
     <fo:region-before extent="1cm"/> 
     <fo:region-after extent="0cm"/> 
     </fo:simple-page-master> 

     <fo:page-sequence-master master-name="basicPSM" > 
     <fo:repeatable-page-master-alternatives> 
      <fo:conditional-page-master-reference master-reference="first" page-position="first" /> 
      <fo:conditional-page-master-reference master-reference="rest" page-position="rest" /> 
      <!-- recommended fallback procedure --> 
      <fo:conditional-page-master-reference master-reference="rest" /> 
     </fo:repeatable-page-master-alternatives> 
     </fo:page-sequence-master> 

    </fo:layout-master-set> 
    <!-- end: defines page layout --> 

    <!-- actual layout --> 
    <fo:page-sequence master-reference="basicPSM"> 

     <fo:flow flow-name="xsl-region-body"> 


    <xsl:template match="/" name="tables"><!--ERROR REFERS TO HERE--> 
    <xsl:param name="pRows" select="3"/> 
    <xsl:param name="pColumns" select="3"/> 
    <xsl:param name="pSequence" select="*/*"/> 
    <xsl:variable name="vSize" select="$pRows * $pColumns"/> 
    <xsl:for-each select="$pSequence[position() mod $vSize = 1]"> 
     <xsl:variable name="vPosition" select="position()"/> 
     <fo:table table-layout="fixed" width="63mm" border-collapse="separate" wrap-option="wrap"> 
     <fo:table-body wrap-option="wrap"> 
      <xsl:call-template name="rows"> 
      <xsl:with-param name="pSequence" 
       select="$pSequence[ 
            position() > ($vPosition - 1) * $vSize 
            and 
            $vPosition * $vSize + 1 > position() 
           ]"/> 
      </xsl:call-template> 
     </fo:table-body> 
     </fo:table> 
    </xsl:for-each> 
    </xsl:template> 


    <xsl:template name="rows"> 
    <xsl:param name="pSequence" select="/.."/> 
    <xsl:param name="pRow" select="$pRows"/> 
    <xsl:if test="$pRow"> 
     <xsl:call-template name="rows"> 
     <xsl:with-param name="pSequence" select="$pSequence"/> 
     <xsl:with-param name="pRow" select="$pRow - 1"/> 
     </xsl:call-template> 
     <fo:table-row wrap-option="wrap"> 
     <xsl:call-template name="columns"> 
      <xsl:with-param name="pSequence" 
       select="$pSequence[ 
            position() > ($pRow - 1) * $pColumns 
            and 
            $pRow * $pColumns + 1 > position() 
           ]"/> 
     </xsl:call-template> 
     </fo:table-row> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template name="columns"> 
    <xsl:param name="pSequence" select="/.."/> 
    <xsl:param name="pColumn" select="$pColumns"/> 
    <xsl:if test="$pColumn"> 
     <xsl:call-template name="columns"> 
     <xsl:with-param name="pSequence" select="$pSequence"/> 
     <xsl:with-param name="pColumn" select="$pColumn - 1"/> 
     </xsl:call-template> 
     <fo:table-cell width="90mm"> 
     <fo:block wrap-option="wrap"> 
      <xsl:apply-templates select="$pSequence[$pColumn]"/> 
     </fo:block> 
     </fo:table-cell> 
    </xsl:if> 
    </xsl:template> 

    <xsl:output method="xml"/> 
    <xsl:template match="/"> 
    <xsl:call-template name="tables"> 
     <xsl:with-param name="pSequence" select="workOrders/workOrder[position()!=1]"/> 
    </xsl:call-template> 
    </xsl:template> 
    <xsl:template match="workOrder"> 
    <xsl:value-of select="PartNumber"/> 
    </xsl:template> 

    </fo:flow> 
    </fo:page-sequence> 
    </fo:root> 
</xsl:stylesheet> 
+0

「的困難的部分是確保他們排列在彼此旁邊列「。 - 這個要求不清楚。這是否意味着困難的部分是將它們分成幾排?哪些細胞應該與哪些細胞排列在一起? – LarsH

+0

你還使用XSLT 2還是必須使用1? 2.0會使這更容易。 – LarsH

+0

@ P.Brian.Mackey:這些表格問題有很多答案。您需要提供減少但有意義的輸入樣本和確切的期望輸出。 – 2011-05-03 22:48:06

回答

3

這XSLT 1.0樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="pRows" select="6"/> 
    <xsl:param name="pColumns" select="3"/> 
    <xsl:variable name="pCells" select="$pRows * $pColumns"/> 
    <xsl:template match="workOrders"> 
     <xsl:apply-templates 
      select="workOrder[position() mod $pCells = 1]" 
      mode="table"/> 
    </xsl:template> 
    <xsl:template match="workOrder" mode="table"> 
     <table> 
      <xsl:apply-templates 
       select="(.|following-sibling::workOrder 
           [$pCells > position()]) 
          [position() mod $pColumns = 1]" 
       mode="row"/> 
     </table> 
    </xsl:template> 
    <xsl:template match="workOrder" mode="row"> 
     <tr> 
      <xsl:apply-templates 
       select="(.|following-sibling::workOrder 
           [$pColumns > position()])" 
       mode="cell"/> 
     </tr> 
    </xsl:template> 
    <xsl:template match="workOrder" mode="cell"> 
     <td> 
      <xsl:value-of select="PartNumber"/> 
     </td> 
    </xsl:template> 
</xsl:stylesheet> 

輸出(47個workOrder S):

<table> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
    <tr> 
     <td>110022</td> 
     <td>110022</td> 
    </tr> 
</table> 
+1

+1是的,它做到了! Yatah!因此,未來FO實現者的唯一其他小細節是您需要確保'xmlns:fo =「http://www.w3.org/1999/XSL/Format」'在'xsl:stylesheet'處定義級別不是'fo:root'! –

1

如果你知道有不超過18臺的訂單,你可以使用這樣的事情:

<xsl:if test="Order"> 
    <tableRow> 
    <xsl:apply-templates select="Order[position() &lt;= 6]" /> 
    </tableRow> 
    <xsl:if test="Order[7]"> 
    <tableRow> 
     <xsl:apply-templates select="Order[position() &lt;= 12 and position() > 6]" /> 
    </tableRow> 
    <xsl:if test="Order[13]"> 
     <tableRow> 
     <xsl:apply-templates select="Order[position() &lt;= 18 and position() > 12]" /> 
     </tableRow> 
    </xsl:if> 
    </xsl:if> 
</xsl:if> 

,然後你必須匹配"Order"並輸出一個表格單元格的模板。

不是最大的優雅,但容易。

更新:

OK,赫然發現上面是不是有什麼OP通緝。

下面是一個部分解決方案,用於改寫問題。免責聲明:

  1. 我不知道FO,所以我將該部分留作僞代碼。通過問題標題來判斷,我認爲你需要幫助的部分就是XSLT。

  2. 不確定是否需要關於頁面的總體結構或每個單元格的格式的答案,我已經解決了前者而不是後者。除非我聽到你說這就是你需要的東西,否則我會暫緩花時間在後者上。再次,不知道FO,我不知道你是否可以將每個單元格的內容格式化爲嵌入式表格,這將是排列其列的最簡單的方法。

無論如何,這裏是部分的解決方案:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 
    <xsl:variable name="rowsPerPage" select="6"/> 
    <xsl:variable name="columns" select="3"/> 
    <xsl:variable name="cellsPerPage" select="$rowsPerPage * $columns"/> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="workOrders"> 
     <xsl:for-each-group select="workOrder" 
       group-by="position() idiv $cellsPerPage"> 
     <!-- <page> is pseudocode for FO markup --> 
     <page> 
      <xsl:for-each-group select="current-group()" 
        group-by="position() idiv $columns"> 
       <!-- <row> is pseudocode for FO markup --> 
       <row> 
        <xsl:apply-templates select="current-group()" mode="cell"/> 
       </row> 
      </xsl:for-each-group> 
     </page> 
     </xsl:for-each-group> 
    </xsl:template> 

    <xsl:template match="workOrder" mode="cell"> 
     <!-- <cell> is pseudocode for FO markup --> 
     <cell> 
     <!-- here goes code for laying out the address label --> 
     </cell> 
    </xsl:template> 
</xsl:stylesheet> 
+0

@LarsH:真的嗎?我認爲寫這個比標準解決方案更難。 – 2011-05-03 22:49:34

+0

@Alej:可能對你來說,是的。 :-)但是我想我還沒有掌握標準技術,因爲我更容易這樣思考。 – LarsH

+0

@Alej - 即使現在我也不能想到XSLT 1.0中的更「標準」解決方案比這更容易。我很想看到你的解決方案。 – LarsH