XSL-FO и правильное использование xsl:template и xsl:для каждого

#xml #xslt #xslt-1.0 #xsl-fo

#xml #xslt #xslt-1.0 #xsl-fo

Вопрос:

ниже вы можете увидеть XML и XSL, с помощью которых я пытаюсь его отформатировать. Все работало нормально, пока я не попытался вставить шаблон. Очевидно, я делаю что-то не так. Я пытаюсь использовать template и for-each, чтобы добавить строку в таблицу для каждого <order_line_item> вложенного элемента, <order_line_items> и в каждой из четырех ячеек должно быть четыре значения, вложенных в <order_line_item> Не могли бы вы помочь? Спасибо!

     <hash>
    <order_line_items type="array">
        <order_line_item>
                <document_currency_unit_price_after_discount_value amount="300.0" code="GBP">£300.00</document_currency_unit_price_after_discount_value>
                <document_currency_net_after_main_discount amount="300.0" code="GBP">£300.00</document_currency_net_after_main_discount>
                <description>Subscription</description>
                <unit_quantity type="decimal">1.0</unit_quantity>
        </order_line_item>
        <order_line_item>
            <document_currency_unit_price_after_discount_value amount="300.0" code="GBP">£200.00</document_currency_unit_price_after_discount_value>
                <document_currency_net_after_main_discount amount="300.0" code="GBP">£200.00</document_currency_net_after_main_discount>
                <description>Additional Services</description>
                <unit_quantity type="decimal">1.0</unit_quantity>
        </order_line_item>
        <order_line_item>
            <document_currency_unit_price_after_discount_value amount="300.0" code="GBP">£-50.00</document_currency_unit_price_after_discount_value>
                <document_currency_net_after_main_discount amount="300.0" code="GBP">£-50.00</document_currency_net_after_main_discount>
                <description>Discount</description>
                <unit_quantity type="decimal">1.0</unit_quantity>
        </order_line_item>
    </order_line_items>
</hash>
 

XSL

     <?xml version="1.0" encoding="UTF-8"?>
<xslt:stylesheet xmlns:date="http://exslt.org/dates-and-times" xmlns:str="http://exslt.org/strings" xmlns:xslt="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xf="http://www.ecrion.com/xf/1.0" xmlns:xc="http://www.ecrion.com/2008/xc" xmlns:xfd="http://www.ecrion.com/xfd/1.0" xmlns:svg="http://www.w3.org/2000/svg" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" extension-element-prefixes="date str">
  <xslt:output indent="yes" encoding="utf-8"/>
  
  <xsl:template match="/">
    <fo:root font-size="9pt">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="A4" page-width="210mm" page-height="297mm">
           <fo:region-body region-name="xsl-region-body" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px" margin-top="15mm" margin-bottom="15mm" margin-left="1.5cm" margin-right="1.5cm" border-style="none" border-width="0px" border-color="" background="" background-repeat="no-repeat" background-position-horizontal="0px" background-position-vertical="0px" extent="0px" column-gap="0px" column-count="1" reference-orientation="0"/>
           <fo:region-before region-name="xsl-region-before" display-align="after" extent="15mm" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px" border-style="none" border-width="0px" border-color="" background="" background-repeat="no-repeat" background-position-horizontal="0px" background-position-vertical="0px" reference-orientation="0"/>
           <fo:region-after region-name="xsl-region-after" display-align="before" extent="15mm" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px" border-style="none" border-width="0px" border-color="" background="" background-repeat="no-repeat" background-position-horizontal="0px" background-position-vertical="0px" reference-orientation="0"/>
           <fo:region-start region-name="xsl-region-start" extent="1.5cm" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px" border-style="none" border-width="0px" border-color="" background="" background-repeat="no-repeat" background-position-horizontal="0px" background-position-vertical="0px" reference-orientation="0"/>
           <fo:region-end region-name="xsl-region-end" extent="1.5cm" padding-top="0px" padding-bottom="0px" padding-left="0px" padding-right="0px" border-style="none" border-width="0px" border-color="" background="" background-repeat="no-repeat" background-position-horizontal="0px" background-position-vertical="0px" reference-orientation="0"/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="A4">
        
        <fo:flow flow-name="xsl-region-body">

<fo:table margin-bottom="5mm">
                <fo:table-column column-width="25%"/>
                <fo:table-column column-width="25%"/>
                <fo:table-column column-width="25%"/>
                <fo:table-column column-width="25%"/>
                    <fo:table-body>
                        <fo:table-row>
                        <fo:table-cell>
                            <fo:block>
                                Product
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                Quantity
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                Unit Price
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                Net Amount
                            </fo:block>
                        </fo:table-cell>
                      </fo:table-row>
                    <xsl:template match="hash/order_line_items">
                      <fo:table-row>
                      <xsl:for-each select="order_line_item">
                        <fo:table-cell>
                            <fo:block>
                                <xsl:value-of select="description">
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                <xsl:value-of select="document_currency_unit_price_after_discount_value">
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                <xsl:value-of select="document_currency_unit_price_after_discount_value">
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <fo:block>
                                <xsl:value-of select="unit_quantity">
                            </fo:block>
                        </fo:table-cell>
                        </xsl:for-each>
                      </fo:table-row>
                    </xsl:template>
                </fo:table-body>
        </fo:table>
 </fo:flow>
      </fo:page-sequence>
    </fo:root>  
  </xsl:template>
 </xslt:stylesheet>
 

Комментарии:

1. Шаблоны не могут быть вложенными. Используйте либо один шаблон с вложенными xsl:for-each инструкциями, либо несколько шаблонов с xsl:apply-templates инструкцией, передающей следующий уровень узлов следующему шаблону.

2. @michael.hor257k спасибо, я понял суть, но не могли бы вы привести мне пример? К сожалению, это не моя чашка чая, но, тем не менее, мне нужно разобраться с этим для работы.

Ответ №1:

Как я уже говорил в комментариях, шаблоны не могут быть вложенными. Вам нужно использовать либо один шаблон с вложенными xsl:for-each инструкциями, либо несколько шаблонов с xsl:apply-templates инструкцией, передающей следующий уровень узлов следующему шаблону.

В данном примере вам нужен только один шаблон с одной xsl:for-each инструкцией для создания строки таблицы для каждого order_line_item . Поскольку вы хотите заполнить ячейки в строках в порядке, отличном от того, который используется во входных данных, было бы лучше заполнить их по отдельности.

Вот упрощенный пример (создание таблицы HTML):

XSLT 1.0

 <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/hash">
    <table>
        <!-- header row -->
        <tr>
            <th>Product</th>
            <th>Quantity</th>
            <th>Unit Price</th>
            <th>Net Amount</th>
        </tr>
        <!-- data rows -->  
        <xsl:for-each select="order_line_items/order_line_item">
            <tr>
                <td>
                    <xsl:value-of select="description"/>
                </td>
                <td>
                    <xsl:value-of select="unit_quantity"/>
                </td>
                <td>
                    <xsl:value-of select="document_currency_unit_price_after_discount_value"/>
                </td>
                <td>
                    <xsl:value-of select="document_currency_net_after_main_discount"/>
                </td>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>