Выбор текста между двумя самозакрывающимися тегами через XSLT - PullRequest
1 голос
/ 28 января 2020

Я пытаюсь выделить текст рядом с определенными самозакрывающимися элементами маркера. Вот что у меня есть.

Источник:

<markers>
    <self_closing_marker id="1"/> Some content, possible <othernodes>nodes with text</othernodes>
    <self_closing_marker id="2-3"/> Some more content
</markers>

XSLT:

<xsl:template name="markers" match="self_closing_marker">
    <xsl:value-of select="following-sibling::text()" />
</xsl:template>

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

Конечная цель - получить что-то вроде

<markers>
    <marker id="1">Some content, possible nodes with text</marker>
    <marker id="2-3">Some more content</marker>
</markers>

Ответы [ 3 ]

1 голос
/ 28 января 2020

Вы можете посмотреть на это с противоположной стороны:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="txt" match="text()" use="generate-id(preceding::self_closing_marker[1])" />

<xsl:template match="/markers">
    <xsl:copy>
        <xsl:apply-templates select="self_closing_marker"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="self_closing_marker">
    <marker id="{@id}">
        <xsl:copy-of select="key('txt', generate-id())"/>
    </marker>
</xsl:template>

</xsl:stylesheet>

Демонстрация: https://xsltfiddle.liberty-development.net/bwe3bR/1


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

<xsl:template match="self_closing_marker[key('txt', generate-id())]">
1 голос
/ 28 января 2020

Одним из способов будет присвоение переменной end с первым элементом self_closing_marker на оси following-sibling::.

Затем примените фильтр предикатов для узлов text() на following:: ось для проверки наличия $end и того, что первый элемент self_closing_marker, следующий за этим text(), совпадает с $end путем сравнения сгенерированных значений идентификатора.

<xsl:template name="markers" match="self_closing_marker">
    <xsl:variable name="end" select="following-sibling::self_closing_marker[1]"/>
    <xsl:value-of select="following::text()[
                            $end 
                            and generate-id(following::self_closing_marker[1]) = generate-id($end)
                          ]" />
</xsl:template>
0 голосов
/ 28 января 2020

Если вы готовы использовать функцию расширения Saxon (требуется PE или выше), вы можете использовать:

saxon:leading(
   following-sibling::node(), 
   function($x){exists($x/self::marker)})

См. http://www.saxonica.com/documentation/index.html#! Functions / saxon / lead

Функция возвращает все элементы в последовательности, вплоть до первого, где предоставленный предикат возвращает true.

Вы также можете реализовать эту функцию самостоятельно, но, поскольку она использует функции более высокого порядка, она все равно нужен Saxon-PE или выше.

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

...