XSLT - производит адресные метки - PullRequest
3 голосов
/ 03 мая 2011

ОБНОВЛЕНИЕ Перефразируя вопрос, проясните путаницу.

Я использую XSLT и XSL: FO в переводе Apache FOP.Я хочу напечатать адресные этикетки.

ВХОД

<?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>

ВЫХОД Страница 1 (полная страница 6 строк х 3 столбца)Page1

Страница 2 аналогична странице 1.

Страница 3 (частичная страница ... в данном случае 4 строки х 3 столбца и последний элемент пуст)

Page3

UPDATE2 Я подключил решение Алехандро.Я получаю сообщение об ошибке, о котором сообщает Apache FOP:

xsl: шаблон не разрешен в этой позиции в таблице стилей

Вот код, переведенный из 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>

Ответы [ 2 ]

3 голосов
/ 04 мая 2011

Эта таблица стилей 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 с):

<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 голос
/ 04 мая 2011

Если вы знаете, что не более 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" и выводит ячейку таблицы.

Не очень элегантно, но легко.

Обновление:

ОК, выяснилось, что вышесказанное не было тем, что хотел ОП.

Ниже приведено частичное решение перефразированного вопроса. Отказ от ответственности:

  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>
...