XSLT Группировка и цикл по группе

У меня есть следующий XML:

    <DropDownList id="Dropdown">
        <Label text="Dropdown"/>
        <ListItem value="Test1"/>
        <ListItem value="Test2"/>
    </DropDownList>

    <ListBox id="Listbox1" >
        <Label text="SingleSelect"/>
        <ListItem value="Test1"/>
        <ListItem value="Test2"/>
    </ListBox>

Затем у меня есть следующий XSLT для списка:

<xsl:template match="ListBox">
    <th>
        <xsl:apply-templates select="./Label" />
    </th>
    <td>
        <asp:ListBox runat="server" ID="{@id}">
            <Items>
                <xsl:for-each select="./ListItem">
                    <asp:ListItem Value="{@value}">
                        <xsl:attribute name="Text">
                            <!-- fill text accordingly to text attribute or same as value when not specified-->
                            <xsl:choose>
                                <xsl:when test="@text">
                                    <xsl:value-of select="@text"/>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:value-of select="@value"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:attribute>

                        <xsl:if test="@selected">
                            <xsl:attribute name="selected">
                                <xsl:value-of select="@selected"/>
                            </xsl:attribute>
                        </xsl:if>
                    </asp:ListItem>
                </xsl:for-each>
            </Items>
        </asp:ListBox>
    </td>
    <td>
        <xsl:apply-templates select="./*[contains(name(), 'Validation')]" />
    </td>
    <xsl:copy-of select="$br"/>
</xsl:template>

Используя этот подход, мне пришлось бы дублировать весь цикл и для элемента DropDownList.

Теперь, чтобы избежать дублирования, я понимаю, что могу сделать что-то вроде этого:

<xsl:template match="ListBox">
    <th>
        <xsl:apply-templates select="./Label" />
    </th>
    <td>
        <asp:ListBox runat="server" ID="{@id}">         
            <Items>
                <xsl:apply-templates select="./ListItem" />
            </Items>
        </asp:ListBox>
    </td>
    <td>
        <xsl:apply-templates select="./*[contains(name(), 'Validation')]" />
    </td>
    <xsl:copy-of select="$br"/>
</xsl:template>


<!-- Helper template for list items -->
<xsl:template match="ListItem">
    <asp:ListItem Value="{@value}">
        <xsl:attribute name="Text">
            <!-- fill text accordingly to text attribute or same as value when not specified-->
            <xsl:choose>
                <xsl:when test="@text">
                    <xsl:value-of select="@text"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="@value"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>

        <xsl:if test="@selected">
            <xsl:attribute name="selected">
                <xsl:value-of select="@selected"/>
            </xsl:attribute>
        </xsl:if>
    </asp:ListItem>
</xsl:template>

Но что мне не нравится в этом, так это

            <Items>
                <xsl:apply-templates select="./ListItem" />
            </Items>

образец, который я должен был бы продублировать. Есть ли способ полностью поместить часть <Items> {loop through ListItems}</Items> в шаблон и использовать <xsl:apply-templates select="??" /> для группировки всех дочерних узлов ListItem вместе и включения их в шаблон цикла?


person Sebastian P.R. Gingter    schedule 26.08.2011    source источник
comment
Я не уверен, правильно ли я понимаю вашу проблему, но не получится ли просто использовать <xsl:template match="ListBox|Dropdown">...</xsl:template>?   -  person Boldewyn    schedule 26.08.2011
comment
Нет, потому что DropDown использует тег <asp:DropDown> и имеет другие атрибуты. Существуют также элементы CheckBoxList и RadioButtonList, которые имеют другие особенности.   -  person Sebastian P.R. Gingter    schedule 26.08.2011
comment
Итак, какой результат вы хотите получить и не могли бы вы объяснить какие-то правила его получения?   -  person Dimitre Novatchev    schedule 26.08.2011


Ответы (2)


Почему бы не использовать именованный шаблон?

<td>
        <asp:ListBox runat="server" ID="{@id}">
         <xsl:call-template name="LoopItems"/>
        </asp:ListBox>
</td>

с именованным шаблоном:

<xsl:template name="LoopItems">
  <Items>
    <xsl:apply-templates select="ListItem" />
  </Items>
</xsl:template>
person Emiliano Poggi    schedule 28.08.2011
comment
Как будет выглядеть именованный шаблон в описанном мной случае? - person Sebastian P.R. Gingter; 29.08.2011
comment
Что ж, названный шаблон - это именно то, что вы хотите, чтобы не повторялись в различных ситуациях (я думаю). - person Emiliano Poggi; 29.08.2011
comment
Смотрите мой ответ сейчас, надеюсь, я понял ваш вопрос. - person Emiliano Poggi; 29.08.2011
comment
О, это было так прямолинейно, что я этого не заметил. Здесь еще раннее утро без кофе. Спасибо :) - person Sebastian P.R. Gingter; 29.08.2011

Что насчет этого шаблона:

<xsl:template match="ListBox|DropDownList">
  <th>
    <xsl:apply-templates select="Label" />
  </th>
  <td>
    <xsl:element name="asp:{name()}">
      <Items>
        <xsl:apply-templates select="ListItem" />
      </Items>
    </xsl:element>
  </td>
  <td>
    <xsl:apply-templates select="*[contains(name(), 'Validation')]" />
  </td>

</xsl:template>
person Kirill Polishchuk    schedule 28.08.2011