Выберите те же узлы, которые существуют последовательно - PullRequest
0 голосов
/ 07 мая 2019

У меня есть XML, и я хочу выбрать те же узлы, которые появляются последовательно.

<main>
    <topic1>
        <ntb>1</ntb>
        <ifs>2</ifs>
        <jst>3</jst>
        <ifs>4</ifs>
    </topic1>
    <topic2>
        <ifs>1</ifs>
        <ntb>2</ntb>
        <jst>3</jst>
        <ifs>4</ifs>
        <ifs>5</ifs>
    </topic2>
</main>

Я попробовал следующий код:

<xsl:template match="topic2/ifs">
    <count_node>
        <xsl:apply-templates/>
    </count_node>
</xsl:template>

Когда я попробовал вышеуказанный код, все <ifs> теги выбраны.

Я хочу выбрать два последних<ifs> теги внутри <topic2> тега с использованием XPath, поскольку они являются последовательными

ожидаемый результат:

<count_node>
    <ifs>4</ifs>
    <ifs>5</ifs>
</count_node>

Ответы [ 3 ]

0 голосов
/ 07 мая 2019

Попробуйте это:

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

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />

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

<xsl:template match="topic2/ifs[preceding-sibling::node()[1][self::ifs] or following-sibling::node()[1][self::ifs]]">
    <xsl:copy-of select="."/>
</xsl:template>

<xsl:template match="text()" />
</xsl:stylesheet>

См. Демонстрацию здесь: https://xsltfiddle.liberty -development.net / gWvjQfD / 1

Примечание: Приведенное выше решение заполнит все последовательные <ifs> узлы в <topic2>

0 голосов
/ 07 мая 2019

Предполагая, что вы можете использовать XSLT 2 или более позднюю версию, вы можете написать шаблон для topic2 элементов, который находит и объединяет группы по крайней мере из двух ifs дочерних элементов с

  <xsl:template match="topic2">
      <xsl:for-each-group select="*" group-adjacent="boolean(self::ifs)">
          <xsl:if test="current-grouping-key() and current-group()[2]">
              <count_node>
                  <xsl:copy-of select="current-group()"/>
              </count_node>
          </xsl:if>
      </xsl:for-each-group>
  </xsl:template>

Полный пример на https://xsltfiddle.liberty -development.net / jyRYYiF , использует Saxon 9.8, так же как и XSLT 3, но шаблон выше использует только функции, уже доступные в XSLT 2.

0 голосов
/ 07 мая 2019

Вот xpath для последовательного получения 2-го узла с тем же именем.

//*[local-name()=name(following-sibling::*)]/following-sibling::*

Вы можете использовать либо имя, либо локальное имя.

//*[name()=name(following::*)]/following-sibling::*

Редактировать:

Вот xpath для выбора всех элементов, которые являются последовательными и имеют одинаковое имя тега (работает, даже если у вас есть более 2 последовательных элементов с одинаковым тегом)

//*[name()=name(following-sibling::*[1])]|//*[name()=name(preceding-sibling::*[1])]

К вашему сведению: у меня естьне жестко закодировано имя тега, поэтому он будет выбирать любой тег, который является последовательным, если вы ищете конкретный тег, пожалуйста, обновите * с именем тега.

Редактировать: xpath используется OP.

//ifs[following-sibling::*[1][self::ifs] or preceding-sibling::*[1][self::ifs]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...