2010-02-04 3 views
0

Я хочу сделать что-то похожее на следующее:динамически начать XSLT и близкие теги

<xsl:for-each select="Item"> 
    <xsl:if test="postion()=1 or position()=7> 
    <ul> 
    </xsl:if> 
    <li>An Item</li> 
    <xsl:if test="position()=2"> 
    </ul> 
    </xsl> 
</xsl:for-each> 
</ul> 

Это не будет работать, однако, потому что XSLT рассматривает незамкнутую <ul> в заявлении, если недействительным.

ввода пробы:

<Item>1</Item> 
<Item>2</Item> 

<Item>3</Item> 

<Item>4</Item> 

<Item>5</Item> 

<Item>6</Item> 

<Item>7</Item> 

<Item>8</Item> 

<Item>9</Item> 

<Item>10</Item> 

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

<ul> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
</ul> 
<ul> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
<li>An Item<li> 
</ul> 

Благодаря -Бен

+0

Не могли бы вы привести пример вашего ожидаемого результата? – aefxx

+0

Могу ли я написать ответ на основе 'disable-output-encoding'? –

+0

отредактируйте ваш ответ и удалите этот комментарий, plz –

ответ

2

Вы должны переписать его, чтобы избежать необходимости такой тег супа. Первая группа элементов, так что каждая группа преобразуется в свой собственный UL на выходе, а затем перебирает эти группы (и для каждой группы - итерации по элементам внутри).

Для конкретного кода, который вы в курсе, с закодированных значений, это тривиально переработан, перемещая выход для Item в свой собственный шаблон (хорошая идея, во всяком случае), а затем повторно использовать, что:

<xsl:template match="Item"> 
    <li>An Item</li> 
</xsl:template> 

... 

<ul> 
    <xsl:apply-templates select="Item[1]"/> 
</ul> 
<ul> 
    <xsl:apply-templates select="Item[position() &ge; 2 and position() &le; 7]"/> 
</ul> 
<xsl:apply-templates select="Item[position() &gt; 7]"/> 

На практике у вас, вероятно, есть еще более сложный способ определения границ ваших групп, но, не зная точного требования, трудно быть более конкретным при ответе на это. Вероятно, вы захотите посмотреть на группировку Muenchian method, если вы используете какой-то ключ. Если ваши группы имеют фиксированный размер, с несколькими жестко закодированными исключениями (например, первый элемент в своей группе, а затем каждый следующий 10 элементов образуют новую группу), вы можете вместо этого перебирать позицию.

+0

Спасибо, это почти то же самое, что я в конечном итоге использовал (с немного большей логикой, чтобы сделать то, что мне нужно было сделать ...) Большое спасибо – Ben

2

Если вы хотите просто группировать элементы в группы из шести (или меньше, в конце), то вы можете использовать рекурсивный вызов шаблону, который выплескивает первые шесть элементов в списке, а затем вызывает себя для любой оставшийся.

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="1.0"> 
<xsl:output method="xml" indent="no" encoding="ISO-8859-1"/> 

<xsl:template match="Item"> 
<li>Item</li> 
</xsl:template> 

<xsl:template name="group-of-six"> 
    <xsl:param name="items"/> 

    <ul> 
    <xsl:for-each select="$items[position() &lt; 7]"> 
    <xsl:apply-templates select="."/> 
    </xsl:for-each> 
    </ul> 

    <xsl:if test="count($items) &gt; 6"> 
     <xsl:call-template name="group-of-six"> 
      <xsl:with-param name="items" select="$items[position() &gt; 6]"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="/"> 
    <Lists> 
    <xsl:call-template name="group-of-six"> 
     <xsl:with-param name="items" select="//Item"/> 
    </xsl:call-template> 
    </Lists> 
</xsl:template> 

</xsl:transform> 
0

Хотя ответы, указывающие, что вы должны написать это с помощью шаблонов таким образом, чтобы избежать этого безобразия правильны, быстрый и грязный раствор вы ищете заключается в следующем. Ваш код XSLT должен быть изменен следующим образом:

<xsl:for-each select="Item"> 
    <xsl:if test="postion()=1 or position()=7> 
    <ul> 
    </xsl:if> 
    <li>An Item</li> 
    <xsl:if test="position()=2"> 
    </ul> 
    </xsl> 
</xsl:for-each> 
</ul> 

Для этого:

<xsl:for-each select="Item"> 
    <xsl:if test="postion()=1 or position()=7> 
    <xsl:text disable-output-escaping="yes"><![CDATA[<ul>]]></xsl:text> 
    </xsl:if> 
    <li>An Item</li> 
    <xsl:if test="position()=2"> 
    <xsl:text disable-output-escaping="yes"><![CDATA[</ul>]]></xsl:text> 
    </xsl> 
</xsl:for-each> 
</ul> 

Другими словами, оберните XML вы пытаетесь вывести с

<xsl:text disable-output-escaping="yes"><![CDATA[ 

и

]]></xsl:text> 
+0

И когда вы получаете вход, который имеет только один «Элемент», в результате вы получаете результат, который не является корректным. По этому конкретному вопросу и большинству других вопросов XSLT я бы никогда не рекомендовал DOE. –

Смежные вопросы