Условное XSLT-преобразование в PHP - PullRequest
0 голосов
/ 25 августа 2009

У меня есть кусок XML данных, которые мне нужно преобразовать в WML.

Это примерно так:

 <root>
  <category name="music"/>
  <subcategory name="classic"/>
  <subcategory name="rock"/>
  <subcategory name="Techno"/>
  <node type="music" subtype="classic" name="beethoven"/>
  <node type="music" subtype="classic" name="chopin"/>
  <record author="beethoven" name="moonlight sonata"/>
  …
 </root>

Я не могу изменить структуру файла.

Некоторые Nokia мобильные браузеры не могут загружать много <card> в память.

Таким образом, в зависимости от мобильного браузера страница WML должна представлять собой либо целый набор <card>, либо некоторое подмножество <card>.

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

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="#music">music</a></p>
  <p><a href="#video">video</a></p>
  <p><a href="#java">java</a></p>
 </card>
 <card id="az">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 <card id="music">
  <p><a href="#classic">classic</a></p>
  <p><a href="#rock">rock</a></p>
  <p><a href="#Techno">Techno</a></p>
 </card>
 <card id="classic">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 …
</wml>

, чтобы пользователь мог просматривать без дополнительных обращений к серверу.

Однако, когда я использую Nokia и захожу на стартовую страницу, страница должна выглядеть следующим образом:

http://example.com/

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="#music">music</a></p>
  <p><a href="#video">video</a></p>
  <p><a href="#java">java</a></p>
 </card>
 <card id="az">
  <p><a href="/beethoven">beethoven</a></p>
  <p><a href="/chopin">chopin</a></p>
 </card>
 <card id="music">
  <p><a href="/classic">classic</a></p>
  <p><a href="/rock">rock</a></p>
  <p><a href="/Techno">Techno</a></p>
 </card>
 <card id="video">
  <p><a href="/movies">Movies</a></p>
 </card>
 <card id="java">
  <p><a href="/games">Games</a></p>
 </card>
</wml>

, когда я посещаю href, там должно отображаться внутреннее содержимое:

http://example.com/classic

<wml>
 <card id="TOC">
  <p><a href="#contents">Contents</a></p>
  <p><a href="#az">A-Z</a></p>
 </card>
 <card id="contents">
  <p><a href="/music">music</a></p>
  <p><a href="/video">video</a></p>
  <p><a href="/java">java</a></p>
 </card>
 <card id="az">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 <card id="classic">
  <p><a href="#beethoven">beethoven</a></p>
  <p><a href="#chopin">chopin</a></p>
 </card>
 …
</wml>

Обычно XSLT должен выполнять следующие действия:

  • Примите какой-то параметр того, что должно быть показано: категория, подкатегория и т. Д.

  • Подсчитайте <card>, которые будут показаны.

    1. Если мы загружаем только типы и оглавление, мы получаем 2 карт (мы всегда их показываем)
      • Если мы загружаем только типы и подтипы, мы получаем 10 карточек.
      • Если мы загружаем типы, подтипы и заголовки, мы показываем 100 карточек.
      • Если мы загрузим все, мы покажем 300 карточек.

    Nokia не может обрабатывать более 120 карт, поэтому мы просто останавливаемся на уровне 3.

    Если XML изменяется и уровень 3 требует 130 карт, мы должны остановиться на уровне 2.

  • Не показывать <card>, если оно ниже определенного уровня

  • Замените # (внутренние ссылки) на / (внешние ссылки), если карта не должна отображаться.

Можно ли сделать это в одном XSL файле?

Ответы [ 3 ]

1 голос
/ 26 августа 2009

Я не уверен, что на самом деле вопрос. Как говорится, ответ «да, это возможно» - xsl:if и xsl:choose должно быть вполне достаточно для выполнения всех ваших условий. Вам нужно будет сообщить ограничения (например, тот факт, что результат будет отправлен в Nokia) к таблице стилей через параметры - см. xsl:param.

0 голосов
/ 26 августа 2009

Насколько я понимаю, XSL завершается, поэтому ответ практически на любой вопрос "возможно ли?" вопрос будет да. Ответ на вопрос «тебе это понравится?», Может быть, не так сильно: -)

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

Если у ваших форматов есть что-то общее, вы можете СУШИТЬ их, делегируя эти части своим собственным шаблонам или функциям, используя их в шаблонах более высокого уровня для основных форматов. Разделяй и властвуй в принципе.

edit: чтобы быть более точным в том, что я имею в виду под делегированием, я имею в виду явный вызов шаблонов и их параметризацию, например ::

   <xsl:call-template name="showcard">
     <xsl:with-param name="kind" select="nokia"/>
   </xsl:call-template>

С этими шаблонами, в свою очередь, делегируя другим и т. Д. Вы также можете получить много от шаблонов value и apply, направляющих поток к определенным шаблонам. Хотя ваш случай, вероятно, проще, это может привести к более читаемому коду.

0 голосов
/ 26 августа 2009

Я бы предложил создать переменные, которые в сумме подсчитывают все узлы каждого "уровня" (тип, подтип, заголовок и т. Д.) И предоставляют параметр для вашего XSL, указывающий максимальное количество карт для генерации. XSL может выглядеть примерно так:

<xsl:stylesheet …>
  <xsl:param name="max-cards" select="999999"/>

  <xsl:template match="/root">
    <!-- "2" here for the type/TOC cards -->
    <xsl:variable name="nSubs" select="2 + count(subcategory)"/>
    <xsl:variable name="nNodes" select="$nSubs + count(node)"/>
    <xsl:variable name="nRecs" select="$nNodes + count(record)"/>

    <!-- generate types & TOC here -->

    <xsl:if test="$nSubs < $max-cards">
        <!-- generate subtypes here -->
    </xsl:if>

    <xsl:if test="$nNodes < $max-cards">
        <!-- generate titles here -->
    </xsl:if>

    <xsl:if test="$nRecs < $max-cards">
        <!-- generate everything else here -->
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Параметры таблицы стилей могут аналогичным образом использоваться для ограничения генерации верхних уровней, но пример для этого будет слишком длинным для SO. ^. ^

...