2016-02-05 2 views
0

Я пытаюсь отформатировать список, используя ФОРМАТИРУЮЩИЕ ОБЪЕКТЫ, который находится в этом формате.Используйте несколько столбцов, если количество элементов в списке, который будет отображаться, больше, чем 5

XML

<SessionValues> 
     <SessionValue Name=\"Items\"> 
      <Value>Item1</Value> 
      <Value>Item2</Value> 
      <Value>Item3</Value> 
      <Value>Item4</Value> 
      <Value>Item5</Value> 
      <Value>Item6</Value> 
      <Value>Item7</Value> 
      <Value>Item8</Value> 
      <Value>Item9</Value> 
      <Value>Item10</Value> 
      <Value>Item11</Value> 
      <Value>Item12</Value> 
      <Value>Item13</Value> 
      <Value>Item14</Value> 
      <Value>Item15</Value> 
     </SessionValue> 
<SessionValues> 

XSLT

<xsl:template match="Table[@Caption='Proofs']"> 
    <fo:list-block > 
     <xsl:for-each select="key('sessionValues-id','Items')/Value"> 
     <fo:list-item> 
      <fo:list-item-label end-indent="label-end()"> 
      <fo:block> 
       <fo:inline>&#8226;</fo:inline> 
      </fo:block> 
      </fo:list-item-label> 
      <fo:list-item-body start-indent="body-start()" text-align="left" font-size="10pt"> 
      <fo:block text-align="left" font-size="10pt"> 
       <xsl:value-of select="text()"/> 
      </fo:block> 
      </fo:list-item-body> 
     </fo:list-item> 
     </xsl:for-each> 
    </fo:list-block> 
    </xsl:template> 

Это дает мне длинный список всех пунктов. Мне нужно показать это так, чтобы, если количество отображаемых элементов больше 5, оно должно появиться в следующем столбце. Итак, для примера выше должно быть 3 столбца по 5 элементов каждый.

** UPDATE **

Ожидаемый результат

<fo:table> 
    <fo:table-body> 
    <fo:table-row> 
     <fo:table-cell>Item 1</fo:table-cell> 
     <fo:table-cell>Item 2</fo:table-cell> 
     <fo:table-cell>Item 3</fo:table-cell> 
     <fo:table-cell>Item 4</fo:table-cell> 
     <fo:table-cell>Item 5</fo:table-cell> 
    </fo:table-row> 
    <fo:table-row> 
     <fo:table-cell>Item 6</fo:table-cell> 
     <fo:table-cell>Item 7</fo:table-cell> 
     <fo:table-cell>Item 8</fo:table-cell> 
     <fo:table-cell>Item 9</fo:table-cell> 
     <fo:table-cell>Item 10</fo:table-cell> 
    </fo:table-row> 
    <fo:table-row> 
     <fo:table-cell>Item 11</fo:table-cell> 
     <fo:table-cell>Item 12</fo:table-cell> 
     <fo:table-cell>Item 13</fo:table-cell> 
     <fo:table-cell>Item 14</fo:table-cell> 
     <fo:table-cell>Item 15</fo:table-cell> 
    </fo:table-row> 
    </fo:table-body> 
</fo:table> 

** UPDATE - 2 **

Я следую @Franks предложение и создали несколько шаблонов, чтобы быть в зависимости от моего состояния. Что-то вроде этого

<fo:table> 
     <fo:table-column number-columns-repeated="$columns" /> 
     <fo:table-body> 
     <xsl:for-each select="key('sessionValues-id','Items')/Value"> 
      <xsl:choose> 
      <xsl:when test="SomeCondition"> 
       <!-- template with Row and Cell --> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- template with Cell --> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 
     </fo:table-body> 
    </fo:table> 

У меня нет ошибок, но он даже не генерирует ничего. Я подозреваю, что это <fo:table-column number-columns-repeated="$columns" /> Может ли кто-нибудь сказать мне, как мы можем указать количество столбцов в моем случае динамически? Количество столбцов хранится в переменной $columns.

+0

Пожалуйста, ваши ожидаемый выход. –

+1

Отображение ожидаемого результата как XSL-FO будет намного яснее, чем приближение в виде текста. –

+0

Вы можете определить свою переменную столбца, как это: '' – Frank

ответ

0

Вы можете попробовать с помощью следующего кода внутри вашего цикла:

<xsl:choose> 
    <xsl:when test="(position() mod 5) = 0"> 
    <!-- You code for beginning a new column here --> 

    </xsl:when> 
</xsl:choose> 
<!-- here you output your list-item --> 
<xsl:choose> 
    <xsl:when test="(position() mod 5) = 0"> 
    <!-- You code for closing the new column here --> 

    </xsl:when> 
</xsl:choose> 

не самое элегантное решение, но оно должно работать.

+0

Я использую вашу идею, и я думаю, что я почти там. но сталкиваются с какой-то проблемой. См. Мой обновленный запрос. – SkoolCodeian

1

Использовать break-after="column" (или break-before="column") в зависимости от ситуации. См. https://www.w3.org/TR/xsl11/#d0e26492

Для перехода к следующему столбцу требуется, чтобы вы указали, что существует следующий столбец для разрыва. В XSL 1.1 вы указываете column-count на fo:region-body, чтобы установить количество столбцов для fo:region-body для мастера страницы. С AH Formatter, вы можете также установить column-count на индивидуальной fo:block-container (https://www.antennahouse.com/product/ahf63/ahf-ext.html#axf.column-count), как в приведенном ниже примере:

<xsl:template match="SessionValue"> 
    <fo:block-container column-count="{ceiling(count(Value) div 5)}"> 
    <fo:list-block> 
     <xsl:apply-templates select="Value" /> 
    </fo:list-block> 
    </fo:block-container> 
</xsl:template> 

<xsl:template match="Value"> 
    <fo:list-item> 
    <xsl:if test="position() mod 5 = 0"> 
     <xsl:attribute name="break-after">column</xsl:attribute> 
    </xsl:if> 
    <fo:list-item-label end-indent="label-end()"> 
     <fo:block> 
     <fo:inline>&#8226;</fo:inline> 
     </fo:block> 
    </fo:list-item-label> 
    <fo:list-item-body start-indent="body-start()" text-align="left" font-size="10pt"> 
     <fo:block text-align="left" font-size="10pt"> 
     <xsl:value-of select="text()"/> 
     </fo:block> 
    </fo:list-item-body> 
    </fo:list-item> 
</xsl:template> 

Это было в требованиях к XSL 2.0: https://www.w3.org/TR/xslfo20-req/#N66550

Другие форматтеры могут иметь различные механизмы.

Редактировать

Но если у вас есть область с несколькими столбцами (или fo:block-container), верстальщик может сделать лучшую работу по балансировке столбцов на основе отформатированных размера, чем вы можете сделать путем подсчета элементов списка.Если, например, один или несколько элементов списка имели много текста и занимали несколько строк, а другие - нет, тогда у вас были бы неравномерные высоты столбцов, если бы вы вручную вносили разрывы после каждого пятого элемента списка, тогда как formatter может разрываться между столбцами на основе форматированных размеров текста.

0

Чтобы минимизировать пример решаемой задачи:

Пусть даны хорошо сформированные вход:

XML

<SessionValues> 
    <SessionValue Name="Items"> 
    <Value>Item1</Value> 
    <Value>Item2</Value> 
    <Value>Item3</Value> 
    <Value>Item4</Value> 
    <Value>Item5</Value> 
    <Value>Item6</Value> 
    <Value>Item7</Value> 
    <Value>Item8</Value> 
    <Value>Item9</Value> 
    <Value>Item10</Value> 
    <Value>Item11</Value> 
    <Value>Item12</Value> 
    <Value>Item13</Value> 
    <Value>Item14</Value> 
    <Value>Item15</Value> 
    </SessionValue> 
</SessionValues> 

следующая таблица стилей:

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:strip-space elements="*"/> 

<xsl:variable name="columns" select="5" /> 

<xsl:template match="SessionValue"> 
    <table> 
     <xsl:for-each select="Value[position() mod $columns = 1]" > 
      <tr> 
       <xsl:for-each select=". | following-sibling::Value[position() &lt; $columns]"> 
        <td><xsl:value-of select="."/></td> 
       </xsl:for-each> 
      </tr> 
     </xsl:for-each> 
    </table> 
</xsl:template> 

</xsl:stylesheet> 

вернется:

Результат

<?xml version="1.0" encoding="UTF-8"?> 
<table> 
    <tr> 
     <td>Item1</td> 
     <td>Item2</td> 
     <td>Item3</td> 
     <td>Item4</td> 
     <td>Item5</td> 
    </tr> 
    <tr> 
     <td>Item6</td> 
     <td>Item7</td> 
     <td>Item8</td> 
     <td>Item9</td> 
     <td>Item10</td> 
    </tr> 
    <tr> 
     <td>Item11</td> 
     <td>Item12</td> 
     <td>Item13</td> 
     <td>Item14</td> 
     <td>Item15</td> 
    </tr> 
</table> 
+0

Извините, но мне нужно использовать форматирующие объекты, поскольку я создаю PDF из этого. Добавлено это на мой вопрос сейчас. – SkoolCodeian

+0

@SkoolCodeian Это возвращает результат, который вы попросили. Если вам нужен другой результат, разумная вещь - отредактировать ваш вопрос и показать ** точный ** вывод (** как код **), который вы ожидаете получить. –

+0

@SkoolCodeian Корректировка, необходимая для получения этого результата, тривиальна. –