Создайте массив переменных с динамическими именами с помощью xslt - PullRequest
0 голосов
/ 06 марта 2019

Я хотел бы создать массив переменных с динамическими именами и именами режимов.Кроме того, эти переменные представляют собой цепочку, которая обрабатывает document-node () пошагово.Поэтому вместо того, чтобы писать так:

<xsl:variable name="A">
    <xsl:apply-templates mode="A" select="."/>
</xsl:variable>
<xsl:variable name="B">
    <xsl:apply-templates mode="B" select="$A"/>
</xsl:variable>
<xsl:variable name="C">
    <xsl:apply-templates mode="C" select="$B"/>
</xsl:variable>

Я хотел бы сделать что-то вроде этого:

<xsl:variable name="mode-names" select="'A', 'B', 'C'"/>

<xsl:variable name="vars">

    <xsl:for-each select="$mode-names">
        <xsl:variable name="pos" select="position()" />     

        <xsl:variable name="{.}">
            <xsl:apply-templates mode="{.}" select="if ($pos=1) then . else $modi[$pos -1]"/>
        </xsl:variable>

    </xsl:for-each>
</xsl:variable>

Сообщение об ошибке: Неверное имя переменной: Неверное имя QName {{.}}

xslt 3.0

1 Ответ

1 голос
/ 06 марта 2019

Непонятно, как бы вы хотели использовать xsl:variable name="{.}" в любом случае, если вы хотите сохранить более одного элемента в переменной, вы, конечно, можете использовать последовательность элементов, так что для вашего случая создания различных документовузлы, вы можете использовать переменную типа document-node()*, которая обозначает последовательность документов / узлов документов.

Таким образом, в примере используется три (статических) режима, которые должны применяться, и каждый результат сохраняется как элемент в этой переменнойбудет

<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:output indent="yes"/>

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

  <xsl:template match="foo" mode="A">
      <bar>
          <xsl:apply-templates mode="#current"/>
      </bar>
  </xsl:template>

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

  <xsl:template match="bar" mode="B">
      <whatever>
          <xsl:apply-templates mode="#current"/>
      </whatever>
  </xsl:template>

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

  <xsl:template match="text()" mode="C">
      <xsl:value-of select="upper-case(.)"/>
  </xsl:template>

  <xsl:variable name="results" as="document-node()*">
      <xsl:variable name="r1">
          <xsl:apply-templates mode="A"/>
      </xsl:variable>
      <xsl:sequence select="$r1"/>
      <xsl:variable name="r2">
          <xsl:apply-templates select="$r1" mode="B"/>
      </xsl:variable>
      <xsl:sequence select="$r2"/>
      <xsl:apply-templates select="$r2" mode="C"/>
  </xsl:variable>

  <xsl:template match="/">
      <results>
          <xsl:for-each select="$results">
              <result step="{position()}">
                  <xsl:copy-of select="."/>
              </result>
          </xsl:for-each>
      </results>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 3NJ38YX / 1

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

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

    <xsl:param name="mode-names" as="xs:string*" select="'A', 'B', 'C'"/>

    <xsl:param name="stylesheet-template-string" as="xs:string"><![CDATA[
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0" exclude-result-prefixes="#all">

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

            <xsl:template match="foo" mode="A">
                <bar>
                    <xsl:apply-templates mode="#current"/>
                </bar>
            </xsl:template>

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

            <xsl:template match="bar" mode="B">
                <whatever>
                    <xsl:apply-templates mode="#current"/>
                </whatever>
            </xsl:template> 

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

            <xsl:template match="text()" mode="C">
                <xsl:value-of select="upper-case(.)"/>
            </xsl:template>            

        </xsl:stylesheet>
    ]]></xsl:param>

    <xsl:param name="stylesheet-template" select="parse-xml($stylesheet-template-string)"/>

    <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

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

    <xsl:variable name="stylesheet">
        <xsl:apply-templates select="$stylesheet-template" mode="construct-stylesheet"/>
    </xsl:variable>

    <xsl:template match="xsl:stylesheet | xsl:transform" mode="construct-stylesheet">
        <xsl:copy>
            <xsl:apply-templates select="@* , node()" mode="#current"/>

            <axsl:variable name="results" as="document-node()*">
                <xsl:iterate select="$mode-names">
                    <axsl:variable name="result-{.}">
                        <axsl:apply-templates select="{if (position() eq 1) then '.' else '$result-' || subsequence($mode-names, position() - 1, 1)}" mode="{.}"/>
                    </axsl:variable>
                    <axsl:sequence select="$result-{.}"/>
                </xsl:iterate>
            </axsl:variable>

            <axsl:template match="/">
                <results>
                    <axsl:for-each select="$results">
                        <result step="{{position()}}">
                            <axsl:copy-of select="."/>
                        </result>
                    </axsl:for-each>
                </results>
            </axsl:template>          
        </xsl:copy>
    </xsl:template>

    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <xsl:sequence
            select="transform(map {
            'source-node' : .,
            'stylesheet-node' : $stylesheet
            })?output"/>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 3NJ38YX / 2 для одного порядка режимов и https://xsltfiddle.liberty -development.net / 3NJ38YX / 3 для другого порядка.

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

...