Есть ли элегантный способ добавить несколько классов HTML с помощью XSLT?

Допустим, я преобразовываю тест с множественным выбором из произвольного формата XML в HTML. Каждый выбор будет представлен в виде HTML <li> тег в итоговом документе. Для каждого варианта я хочу добавить HTML class из correct к <li> если этот выбор был правильным ответом. Кроме того, если этот выбор был выбран пользователем, я хочу добавить класс submitted к <li>, Следовательно, если выбор является правильным, а также представленным, <li> должен иметь class из correct submitted,

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

Как я могу решить это элегантным способом?

Пример желаемого результата:

<p>Who trained Obi-Wan Kenobi?</p>
<ul>
    <li>Mace Windu</li>
    <li class="correct submitted">Qui-Gon Jinn</li>
    <li>Ki-Adi-Mundi</li>
    <li>Yaddle</li>
</ul>

3 ответа

Решение

Во-первых, в пробелах в значениях атрибутов в XML нет ничего плохого: грубо говоря, нормализация значений атрибутов преобразует пробелы в пробелы и объединяет соседние пробелы в один пробел при анализе документа, но пробел определенно разрешен. РЕДАКТИРОВАТЬ: Смотрите ниже для получения дополнительной информации об этом.

Подход Мэтью Уилсона не включает пробел между возможными значениями, как вы упоминаете в своем комментарии к нему. Однако его подход принципиально обоснован. Последняя часть головоломки - ваша неприязнь к избыточным пробелам: их можно устранить с помощью normalize-space Функция XPath.

Следующая таблица стилей объединяет все биты - обратите внимание, что она ничего не делает со своим входным документом, поэтому в целях тестирования вы можете запустить его для любого XML-документа или даже для самого себя, чтобы убедиться, что вывод соответствует вашим требованиям.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:variable name="foo0" select="false()"/>
  <xsl:variable name="bar0" select="true()"/>

  <xsl:variable name="foo1" select="true()"/>
  <xsl:variable name="bar1" select="false()"/>

  <xsl:variable name="foo2" select="true()"/>
  <xsl:variable name="bar2" select="true()"/>

  <xsl:template match="/">

    <xsl:variable name="foobar0">
      <xsl:if test="$foo0"> foo</xsl:if>
      <xsl:if test="$bar0"> bar</xsl:if>
    </xsl:variable>

    <xsl:variable name="foobar1">
      <xsl:if test="$foo1"> foo</xsl:if>
      <xsl:if test="$bar1"> bar</xsl:if>
    </xsl:variable>

    <xsl:variable name="foobar2">
      <xsl:if test="$foo2"> foo</xsl:if>
      <xsl:if test="$bar2"> bar</xsl:if>
    </xsl:variable>

    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar0)"/>
      </xsl:attribute>
    </li>
    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar1)"/>
      </xsl:attribute>
    </li>
    <li>
      <xsl:attribute name="class">
        <xsl:value-of select="normalize-space($foobar2)"/>
      </xsl:attribute>
    </li>

  </xsl:template>
</xsl:stylesheet>

РЕДАКТИРОВАТЬ: В дополнение к вопросу о пробелах, разделяющих дискретные компоненты в значении атрибута: Спецификация XML определяет ряд возможных допустимых конструкций в качестве типов атрибутов, включая IDREFS и NMTOKENS. Первый случай соответствует производству Имен, а второй случай соответствует производству NMTokens; оба эти произведения определены как содержащие несколько значений соответствующего типа, разделенных пробелами. Таким образом, разделенные пробелами списки значений в качестве значения одного атрибута являются неотъемлемым компонентом информационного набора XML.

Вдобавок ко всему, вы можете создать разделенный пробелами список с чем-то вроде:

<li>
    <xsl:attribute name="class">
        <xsl:if cond="...">correct</xsl:if>
        <xsl:if cond="...">submitted</xsl:if>
  </xsl:attribute>
</li>

Насколько я знаю, значения атрибутов, разделенных пробелами, не являются частью модели данных XML и, следовательно, не могут быть созданы напрямую через XSLT.

Если вы не конвертируете в язык XML (который не является HTML, то есть XHTML), вам не следует беспокоиться о достоверности XML для вывода XSLT. Это может быть что угодно, и не должно соответствовать XML!

Другие вопросы по тегам