XSL - Как определить, является ли элемент последним в серии - PullRequest
11 голосов
/ 12 мая 2010

У меня есть шаблон XSL, выбранный для выполнения (ниже). Что я хотел бы сделать, так это уметь определить, соответствует ли я последнему совпадению Unit.

  <xsl:template match="Unit[@DeviceType = 'Node']">
    <!-- Am I the last Unit in this section of xml? -->
    <div class="unitchild">
      Node: #<xsl:value-of select="@id"/>
    </div>
  </xsl:template>

Пример XML

<Unit DeviceType="QueueMonitor" Master="1" Status="alive" id="7">
    <arbitarytags />
    <Unit DeviceType="Node" Master="0" Status="alive" id="8"/>
    <Unit DeviceType="Node" Master="0" Status="alive" id="88"/>
</Unit>

Ответы [ 4 ]

34 голосов
/ 12 мая 2010

Текущий выбранный ответ обычно неверен!

<xsl:if test="not(following-sibling::Unit)">

Это не будет работать с любым XML-документом и любым <xsl:apply-templates>

Первоначальный вопрос касается последнего Unit, а не последнего брата! Какой из последних сопоставляемых модулей зависит только от выражения в атрибуте select <xsl:apply-templates>, а не от физических свойств документа XML.

Способ сделать это :

<xsl:apply-templates select="SomeExpression"/>

затем в шаблоне, который соответствует узлам, выбранным SomeExpression:

<xsl:if test="position() = last()">
. . . . 
</xsl:if>

Это проверяет, является ли текущий узел последним в node-list, выбранном <xsl:apply-templates>, а не то, что текущий узел является последним братом . Это точно отвечает на оригинальный вопрос.

Если вопрос был сформулирован по-другому, спрашивая, как распознать, является ли последний узел Unit текущим узлом, тогда наилучшим решением было бы указать отдельный шаблон для этого последнего узла:

<xsl:template match="Unit[last()]">
    . . . . 
</xsl:template>

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

8 голосов
/ 12 мая 2010

Если вы хотите проверить, является ли это последний элемент Unit на том же уровне (с тем же родительским элементом), даже если есть произвольные теги до, после и между ними, это будет работать:

<xsl:if test="not(following-sibling::Unit)">

Однако, если вы применяете шаблоны для подмножества, последнее в документе может не входить в обрабатываемый набор. Для этого вы можете проверить, если position() = last()

<xsl:if test="position() = last()">
6 голосов
/ 04 августа 2010

Вы должны проверить position () = last (), но вы должны проверить это в предикате, а не в теле шаблона:

<?xml version="1.0" encoding="utf-8"?>

<data>
    <item group="B">AAA</item>
    <item>BBB</item>
    <item group="B">CCC</item>
    <item>DDD</item>
    <item group="B">EEE</item>
    <item>FFF</item>
</data>

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="data">
    <xsl:apply-templates select="item[@group]"/>
</xsl:template>

<xsl:template match="item">
    ITEM
    <xsl:if test="position() = last()">
    LAST IN CONTEXT
    </xsl:if>
</xsl:template>

<xsl:template match="item[position() = last()]">
    LAST ITEM
</xsl:template>

4 голосов
/ 12 мая 2010

Вы можете проверить position() против last():

<xsl:template match="Unit[@DeviceType = 'Node']">
 <!-- Am I the last Unit in this section of xml? -->     
 <xsl:if test="position() = last()">
   <!-- Yes I am! -->
   Last Unit
 </xsl:if>

 <div class="unitchild">
  Node: #<xsl:value-of select="@id"/>
 </div>
</xsl:template>

См. Статью w3schools по xsl:if.

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