XSLT: проверить, соответствует ли брат или сестра списку условий - PullRequest
0 голосов
/ 04 февраля 2020

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

Если эти условия являются простыми именами тегов, это достаточно просто.

<xsl:param name="tag-list" select="tokenize('img figure table', '\s+')"/>

<xsl:template match="* | text()">
<xsl:variable name="next-name" select="name(following-sibling::*[1])" />
<xsl:if test="$next-name = $tag-list">
<!-- DoSomething -->
</xsl:if>
</xsl:template>

Этот шаблон будет соответствовать любому элементу или текстовому узлу и будет делать DoSomething, если ближайший родственник этого узла либо <img>, <figure> or <table>.

Однако я хочу проверить более сложные условия. Как я могу делать только DoSomething для случаев, когда шаблон соответствует элементам с одноуровневым элементом с указанным атрибутом c, дочерним или текстовым значением? Я бы предпочел сделать это с одним <xsl:if>, так как этот список родственных состояний может быть довольно длинным.

<xsl:param name="tag-list" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>

<xsl:template match="* | text()">
<xsl:if test="???">
<!-- DoSomething -->
</xsl:if>
</xsl:template>

Ответы [ 2 ]

2 голосов
/ 04 февраля 2020

Определите функцию, представляющую ваше сложное условие:

<xsl:function name="my:condition" as="xs:boolean">
  <xsl:param name="node" as="node()"/>
  ... your condition goes here ...
</xsl:function>

, а затем выполните тест:

<xsl:if test="following-sibling::*[1][my:condition(.)]">...</xsl:if>

Если вы хотите модулировать условие в отдельные функции, тогда вы, конечно, можете сделайте так:

<xsl:function name="my:condition" as="xs:boolean">
  <xsl:param name="node" as="node()"/>
  <xsl:sequence select="my:first($node) and my:second($node) and..."/>
</xsl:function>

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

1 голос
/ 04 февраля 2020

Если вы используете XSLT 3, подумайте, позволяет ли параметр stati c с атрибутом shadow создать правильное выражение XPath на лету перед компиляцией таблицы стилей:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="tag-list" static="yes" select="tokenize('img[@src] figure[text()] table[tbody]', '\s+')"/>

  <xsl:template match="* | text()">
    <xsl:if _test="{string-join($tag-list ! ('following-sibling::*[1][self::' || . || ']'), ' | ')}">
        <xsl:comment>DoSomething</xsl:comment>
    </xsl:if>
    <xsl:next-match/>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

При https://xsltfiddle.liberty-development.net/3NSTbf3, который преобразует

<root>
    <section><span>test</span><img src="foo.jpeg"/></section>
    <section>test<table><tbody>...</tbody></table><span>test</span><figure>...</figure></section>
</root>

в

<root>
    <section><!--DoSomething--><span>test</span><img src="foo.jpeg"/></section>
    <section><!--DoSomething-->test<table><tbody>...</tbody></table><!--DoSomething--><span>test</span><figure>...</figure></section>
</root>

Этот пример предназначен для демонстрации использования _test в качестве атрибута тени, я намеренно использовал другой контент шаблона так как кажется более простым показать результат кода с преобразованием идентичности плюс выводимый комментарий, в который входит xsl:if.

...