XSLT, выяснение, является ли последний дочерний узел конкретным элементом - PullRequest
9 голосов
/ 04 октября 2010

Посмотрите на следующие два примера:

<foo>some text <bar/> and maybe some more</foo>

и

<foo>some text <bar/> and a last <bar/></foo>

Смешанные текстовые узлы и bar элементы в элементе foo. Сейчас я нахожусь в foo и хочу узнать, является ли последний ребенок bar. Первый пример должен оказаться ложным, поскольку после bar есть текст, но второй пример должен быть верным.

Как мне это сделать с помощью XSLT?

Ответы [ 3 ]

13 голосов
/ 04 октября 2010

Просто выберите последний узел элемента <foo> и затем используйте ось self для определения типа узла.

/foo/node()[position()=last()]/self::bar

Это выражение XPath возвращает пустой набор (который равен логическому значению false)если последний узел не является элементом.Если вы хотите получить значение true или false, поместите это выражение в функцию XPath boolean().Используйте self::* вместо self::bar для сопоставления любого элемента в качестве последнего узла.

Входной XML-документ:

<root>
    <foo>some text <bar/> and maybe some more</foo>
    <foo>some text <bar/> and a last <bar/></foo>
</root>

Пример документа XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:template match="foo">
    <xsl:choose>
        <xsl:when test="node()[position()=last()]/self::bar">
            <xsl:text>bar element at the end&#10;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>text at the end&#10;</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Вывод таблицы стилей:

text at the end
bar element at the end
7 голосов
/ 04 октября 2010

Сейчас я нахожусь в foo и хочу найти если последний ребенок - bar

Используйте

node()[last()][self::bar]

Логическое значение любого непустого набора узлов - true(), в противном случае оно равно false(). Вы можете использовать вышеприведенное выражение напрямую (без изменений) в качестве значения атрибута test любого <xsl:if> или <xsl:when>.

Лучше, используйте :

foo/node()[last()][self::bar]

как атрибут match для <xsl:template> - таким образом, вы пишете в чистом «push» стиле.

5 голосов
/ 04 октября 2010

Обновление: Этот ответ отвечает требованию, указанному в оригинальном заголовке вопроса: «выяснить, является ли последний дочерний узел текстовым узлом».Но тело вопроса предлагает другое требование, и кажется, что последнее требование было тем, которое было задано ФП.

Предыдущие два ответа явно проверяют, является ли последний дочерний элемент элементом bar,вместо непосредственного тестирования, является ли это текстовым узлом.Это правильно, если foo содержит только «смешанные текстовые узлы и элементы панели» и никогда не имеют нулевых дочерних элементов.

Но вы можете напрямую проверить, является ли последний дочерний элементтекстовый узел:

  1. Для удобочитаемости логики таблицы стилей
  2. В случае, если элемент содержит другие дочерние элементы, кроме элементов и текста: например, комментарии или инструкции по обработке
  3. В случаеэлемент не имеет дочерних элементов

Возможно, вы знаете, что последние два никогда не появятся в вашем случае (но из вашего вопроса я бы предположил, что # 3 мог).Или, может быть, вы так думаете, но не уверены, или, может быть, вы не думали об этом.В любом случае безопаснее напрямую проверить то, что вы действительно хотите знать:

     test="node()[last()]/self::text()"

Таким образом, основываясь на примере кода и ввода @ Dimitre, следующий XML-ввод:

<root>
   <foo>some text <bar/> and maybe some more</foo>
   <foo>some text <bar/> and a pi: <?foopi param=yes?></foo>
   <foo>some text <bar/> and a comment: <!-- baz --></foo>
   <foo>some text and an element: <bar /></foo>
   <foo noChildren="true" />
</root>

С этим шаблоном XSLT:

   <xsl:template match="foo">
      <xsl:choose>
         <xsl:when test="node()[last()]/self::text()">
            <xsl:text>text at the end;&#10;</xsl:text>
         </xsl:when>
         <xsl:when test="node()[last()]/self::*">
            <xsl:text>element at the end;&#10;</xsl:text>
         </xsl:when>
         <xsl:otherwise>
            <xsl:text>neither text nor element child at the end;&#10;</xsl:text>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

выход:

   text at the end;
   neither text nor element child at the end;
   neither text nor element child at the end;
   element at the end;
   neither text nor element child at the end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...