Как я могу оптимизировать XPath тест not(previous-sibling::sect1) для проверки того, является ли это первым дочерним элементом sect1?

Я разрабатываю таблицу стилей XSLT 1.0 (и применяю ее с помощью xsltproc). Один из шаблонов моего скрипта должен выполнять некоторую специальную обработку для первого элемента в данном родительском узле и некоторую для последнего элемента. Сейчас эта специальная обработка реализована следующим образом:

<xsl:template match="sect1">
  <xsl:if test="not(preceding-sibling::sect1)">
    <!-- Special handling for first sect1 element goes here. -->
  </xsl:if>
  <!-- Common handling for all sect1 elements goes here. -->
  <xsl:if test="not(following-sibling::sect1)">
    <!-- Special handling for last sect1 element goes here. -->
  </xsl:if>
</xsl:template>

Мне интересно (просто из любопытства, скорость выполнения скрипта меня устраивает): есть ли более эффективный способ сделать это? Возможно ли, что XSLT-процессор перестанет собирать набор узлов preceding-sibling::sect1 после первого найденного совпадения, потому что он знает, что ему нужно найти только один или ноль элементов?

1
задан Frerich Raabe 27 August 2010 в 13:32
поделиться

2 ответа

Предполагая, что контекст, в котором вызывается шаблон, является выбором дочернего узла, тогда я предлагаю следующее. Если контекст, в котором они были вызваны, был через другую ось (скажем, предыдущий брат или предок), то способ приблизиться к нему лучше всего.

Есть две возможности упростить тесты или заменить их другими шаблонами:

Более простые тесты:

<xsl:template match="sect1">
  <xsl:if test="position() = 1">
    <!-- Special handling for first sect1 element goes here. -->
  </xsl:if>
  <!-- Common handling for all sect1 elements goes here. -->
  <xsl:if test="position() = last()">
    <!-- Special handling for last sect1 element goes here. -->
  </xsl:if>
</xsl:template>

Различные шаблоны:

<xsl:template name="handleSect1">
  <!-- Common handling for all sect1 elements goes here. -->
<xsl:template>
<xsl:template match="sect1">
  <xsl:call-template name="handleSect1"/>
</xsl:template>
<xsl:template match="sect1[1]">
  <!-- Special handling for first sect1 element goes here. -->
  <xsl:call-template name="handleSect1"/>
</xsl:template>
<xsl:template match="sect1[last()]">
  <xsl:call-template name="handleSect1"/>
  <!-- Special handling for last sect1 element goes here. -->
</xsl:template>
<xsl:template match="sect1[position() = 1 and position() = last()]">
  <!-- Special handling for first sect1 element goes here. -->
  <xsl:call-template name="handleSect1"/>
  <!-- Special handling for last sect1 element goes here. -->
</xsl:template>

Поскольку вы говорите «оптимизировать», я предполагаю, что вас волнует, какой из них будет обрабатываться быстрее. Он будет варьироваться в зависимости от процессора xslt, режимов обработки (у некоторых есть опция «компилировать», и это повлияет на то, какой из них более эффективен) и входного XML. Самым быстрым может быть любой из них или ваш оригинал.

На самом деле, каждый из них должен быть столь же эффективным, как и другой, разница заключается в оптимизации, которую процессор может сделать.

В данном случае я бы предпочел первый вариант ответа, так как он наиболее лаконичен, но если бы мне не нужно было использовать общую обработку для всех 4 случаев, я бы предпочел подход во втором ответе, который затем четко отмечает различные подходы для каждого случая.

1
ответ дан 2 September 2019 в 21:46
поделиться

Я думаю, вы должны уметь это делать

  <xsl:if test="position() = 1">
    <!-- Special handling for first sect1 element goes here. -->
  </xsl:if>
  <!-- Common handling for all sect1 elements goes here. -->
  <xsl:if test="position() = last()">
    <!-- Special handling for last sect1 element goes here. -->
  </xsl:if>

,поскольку position() и last() являются контекстно-зависимыми.

0
ответ дан 2 September 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: