2009-08-25 2 views
0

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

Это что-то вроде этого:

<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> 

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

Some 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. Если мы загружаем только тип и TOC, мы получаем 2 карт (мы всегда показываем их)
      • Если мы загружаем только тип и подтипы, мы получаем 10 карты.
      • Если мы загружаем типы, подтипы и заголовки, мы показываем карты 100.
      • Если мы загружаем все, мы показываем карты 300.

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

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

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

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

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

+0

Будет ли только один уровень URL-адреса? Slash + ключевое слово, вот оно что? Разве это не приводит к двусмысленности? Или URL-адрес структурирован? – Tomalak

+0

Нет, не будет. Он был разработан, чтобы держать все карты сразу, и им нужно иметь разные имена. Проблема возникла только при тестировании. – Quassnoi

+0

Таким образом, я могу доверять, что @names будут уникальными во всех категориях/подкатегории/элементах узла/записи? – Tomalak

ответ

1

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

0

Я предлагаю создавать переменные, которые аккуратно подсчитывают все узлы каждого «уровня» (тип, подтип, заголовок и т. Д.) И предоставляют параметр для вашего 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> 

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

0

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

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

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

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

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

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

+0

На самом деле, я хочу иметь шаблон многократного использования, поэтому, если я хочу изменить макет карты, я делаю это в одном месте (как для «Nokia», так и для обычных браузеров). Я знаю о параметрах и выбирает, я просто не могу их правильно использовать, все, что я получаю, выглядит ужасным беспорядком. – Quassnoi

+0

да, но это будет всего лишь один файл xsl, с кучей компонентов xsl: template, чтобы спуститься на вход xml. Я думаю о xsl: template как подпрограмме или процедуре/функции. – frankodwyer