2017-01-30 8 views
0

При попытке реализовать шаблон «Двухэтапный просмотр», как описано Мартином Фаулером, у меня возникли проблемы с тем, чтобы работать с раскраской чередующейся строки таблицы HTML. Это использует функцию XSLT position(). Вы можете увидеть шаблон XSLT для table/row ниже. Однако в выводе атрибут bgcolor элемента tr всегда равен "linen", что указывает на то, что значение position() не изменяется при переходе по table/row элементам. Почему это должно быть?Функция позиции XSLT() не работает, как ожидалось, в двухэтапном представлении

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="screen"> 
    <html> 
     <body bgcolor="white"> 
     <xsl:apply-templates/> 
     </body> 
    </html> 
    </xsl:template> 

    <xsl:template match="title"> 
    <h1> 
     <xsl:apply-templates/> 
    </h1> 
    </xsl:template> 

    <xsl:template match="field"> 
    <p><b><xsl:value-of select="@label"/>: </b><xsl:apply-templates/></p> 
    </xsl:template> 

    <xsl:template match="table"> 
    <table><xsl:apply-templates/></table> 
    </xsl:template> 

    <xsl:template match="table/row"> 
    <xsl:variable name="bgcolor"> 
     <xsl:choose> 
     <xsl:when test="(position() mod 2) = 0">linen</xsl:when> 
     <xsl:otherwise>white</xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 

    <tr bgcolor="{$bgcolor}"><xsl:apply-templates/></tr> 
    </xsl:template> 

    <xsl:template match="table/row/cell"> 
    <td><xsl:apply-templates/></td> 
    </xsl:template> 
</xsl:stylesheet> 

Входной XML:

<?xml version="1.0"?> 
<screen> 
    <title>Dissociation</title> 
    <field label="Artist">Dillinger Escape Plan</field> 
    <table> 
    <row> 
     <cell>Limerent Death</cell> 
     <cell>4:06</cell> 
    </row> 
    <row> 
     <cell>Symptom Of Terminal Illness</cell> 
     <cell>4:03</cell> 
    </row> 
    <row> 
     <cell>Wanting Not So Much To As To</cell> 
     <cell>5:23</cell> 
    </row> 
    </table> 
</screen> 

Выходной HTML:

<html><body bgcolor="white"> 
    <h1>Dissociation</h1> 
    <p><b>Artist: </b>Dillinger Escape Plan</p> 
    <table> 
    <tr bgcolor="linen"> 
     <td>Limerent Death</td> 
     <td>4:06</td> 
    </tr> 
    <tr bgcolor="linen"> 
     <td>Symptom Of Terminal Illness</td> 
     <td>4:03</td> 
    </tr> 
    <tr bgcolor="linen"> 
     <td>Wanting Not So Much To As To</td> 
     <td>5:23</td> 
    </tr> 
    </table> 
</body></html> 

ответ

1

Изменение <table><xsl:apply-templates/></table> в <table><xsl:apply-templates select="row"/></table> или использовать <xsl:strip-space elements="*"/> или, по крайней мере, <xsl:strip-space elements="table"/>. В настоящее время вы обрабатываете все дочерние узлы, включая текстовые узлы с пробелами, таким образом ваша попытка с использованием position() терпит неудачу.

+0

Спасибо, это сработало. Но я действительно не понимаю, почему, конечно, '' будет препятствовать оценке 'position()' test на элементах, отличных от строки? В чем разница между использованием 'match' (которое не работает) и использованием' select = '(что работает)? – amoe

+1

С помощью '' (поскольку это сокращенное выражение для ''), вы выбираете все дочерние узлы для обработки, и таким образом у вас есть различные узлы (XSLT 1.0) или последовательность (XSLT 2.0) обрабатываются по сравнению с ''. Внутри всех дочерних узлов определенный элемент 'row' имеет другую позицию по сравнению с поиском только элементов' row', в частности, с форматированным XML, где между узлами элементов есть текстовые узлы с пробелами. Подробнее см. Https://www.w3.org/TR/xslt#section-Applying-Template-Rules. –

+1

Соответственно https://www.w3.org/TR/xslt20/#applying-templates: «Правило, которое соответствует N-му узлу в отсортированной последовательности, оценивается с этим узлом как элемент контекста, а N - как контекстная позиция, и с длиной сортированной последовательности, как размер контекста ». –