Есть ли элегантный способ добавить несколько классов HTML с помощью XSLT? - PullRequest
6 голосов
/ 26 октября 2009

Допустим, я преобразовываю тест с множественным выбором из произвольного формата 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 ]

10 голосов
/ 26 октября 2009

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

Подход Мэтью Уилсона не включает пробелы между возможными значениями, как вы упоминаете в своем комментарии к нему. Однако его подход принципиально обоснован. Последний кусочек головоломки - ваша неприязнь к избыточным пробелам: их можно устранить с помощью функции <a href="http://www.w3.org/TR/1999/REC-xpath-19991116#function-normalize-space" rel="noreferrer">normalize-space</a> 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. Первый случай соответствует производству Names , а второй случай соответствует производству NMTokens ; оба эти произведения определены как содержащие несколько значений соответствующего типа, разделенных пробелами. Таким образом, разделенные пробелами списки значений как значения одного атрибута являются неотъемлемым компонентом информационного набора XML.

5 голосов
/ 26 октября 2009

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

<li>
    <xsl:attribute name="class">
        <xsl:if cond="...">correct</xsl:if>
        <xsl:if cond="...">submitted</xsl:if>
  </xsl:attribute>
</li>
1 голос
/ 26 октября 2009

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

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

...