2010-07-02 3 views
6
<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xsl:element name="Class">123</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <a lot more xsl:elements> 
    </xsl:when> 
    <tens of more similar xsl:when> 
</xsl:choose> 

Есть ли способ упростить приведенный выше код с условными обозначениями? Для каждого значения класса, заданного объектами, следуют десятки строк с дополнительными атрибутами. Эти атрибуты образуют множества в соответствии со значением класса. Класс 0-99 имеет один набор дополнительных тегов, класс 100-199 в секунду, формирующий кошмар обслуживания, когда один из этих дополнительных наборов тегов изменяется.Условия XSLT/переменная область

Я рассматривал решение, как это:

<xsl:choose> 
    <xsl:when test="long convoluted expression"> 
     <xml:element name="Class">123</xsl:element> 
     <xsl:variable name="outputclass" select="123"> 
    </xml:when> 
    <xsl:when test="next very long expression"> 
     <xml:element name="Class">124</xsl:element> 
     <xsl:variable name="outputclass" select="124"> 
    </xsl:when> 
</xsl:choose> 
<xsl:choose> 
    <xsl:when test="$outputclass > 99"> 
     <xml:elements for classes 100-199 here> 
    </xsl:when> 
<xsl:choose> 

Но, конечно, это не удается, так как outputclass переменная не в том же объеме. Любой способ обойти это?

+0

Это смущает.Это может стать более ясным, если вы добавите образец ввода и вывода документа. –

+0

Хороший вопрос (+1). В моем ответе см. * Реальное * лучшее решение - с полным кодом и пояснениями. :) –

ответ

6

Лучшее решение этой проблемы хорошо известны:

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

<xsl:template match="/"> 
    <xsl:variable name="voutType"> 
     <xsl:choose> 
     <xsl:when test="long convoluted expression">123</xsl:when> 
     <xsl:when test="next very long expression">124</xsl:when> 
     <!-- Etcetera ... --> 
     </xsl:choose> 
    </xsl:variable> 

    <Class><xsl:value-of select="$voutType"</Class> 
     <xsl:choose> 
      <xsl:when test="not($voutType > 99)"> 
       <!-- elements for classes 0 - 99 here --> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- elements for classes 100-199 here --> 
      </xsl:otherwise> 
     <xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

Обратите внимание:

  1. Для того, чтобы дать значения переменной ($voutType) в <xsl:choose> инструкция должна быть внутри корпус <xsl:variable>

  2. Вам нужно только указать <Class> элемент один раз - вне всего остального.

  3. Нельзя использовать <xsl:element>, если имя элемента известно.

+0

Это прекрасное решение. Так же легко поддерживать, как и другие решения, но даже короче. Что вы можете вложить в одну переменную, которую я не знал. Спасибо! – diskis

+0

@ diskis: Я серьезно рад, что вы не приняли мой ответ. Это не показалось достаточным, но я думал, что это может заставить вас идти в правильном направлении. Это определенно кажется лучшим способом. – MJB

+0

Что именно делает любое решение «известным»? – n611x007

0

Я только что сделал XSLT несколько раз, но каждый раз это кажется огромным кошмаром для обслуживания. Во всяком случае, я думаю, вы могли бы установить переменную, говорящую о том, что такое класс, а затем вызвать функцию как xsl: template match с классом как arg. Вы бы объявили эту функцию как имя xsl: template, потому что вы не хотите автоматически ее сопоставлять. Внутри функции вы сможете записать эти 100 значений. Не уверен, помогает ли это, но он упорядочивает код таким образом, который мог бы.

+0

Да, спасибо. Быстрые тесты показывают, что это будет отлично работать для моих целей. Теперь только для того, чтобы освежить синтаксис xml: with-param, и я сделаю все возможное с несколькими меньшими шаблонами. – diskis

1

Если вы пытаетесь сделать его легко указать кучу атрибутов (! не тегов аки элементов), то это звучит для меня как наборы атрибутов, что вам нужно, и вы не можете переменные:

http://www.w3.org/TR/xslt#attribute-sets

Это предполагает, что значения атрибутов сами не зависят от значения класса; только их присутствие.

Если элементы действительно то, что вы имеете в виду, попробуйте использовать именованные шаблоны с входным параметром. На верхнем уровне таблицы стилей:

<xsl:template name="classdef"> 
    <xsl:param name="classid"/> 
    <!-- Note: I put the class elem in here so I don't have to 
     write individual class ids more than once --> 
    <xsl:element name="Class"><xsl:value-of select="$classid"/></xsl:element> 
    <xsl:choose> 
    <xsl:when test="$classid > 99"> 
     ... 
    </xsl:when> 
    </xsl:choose> 
</xsl:template> 

и в вашем другом шаблоне:

<xsl:call-template name="classdef"> 
    <xsl:with-param name="classid">124</xsl:with-param> 
</xsl:call-template> 

Смотрите http://www.w3.org/TR/xslt#variables для получения дополнительной информации о Params.

+0

Спасибо, это по сути то же самое решение, что и MJB, и отлично подойдет для моих нужд. Я вернусь и дам вам верх, когда я получу достаточную репутацию, чтобы сделать это :) – diskis

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