Проблема: элемент SVG <use>преобразуется в строку в шаблоне XSL - PullRequest
1 голос
/ 03 мая 2019

Я довольно новичок в XSL, XPATH и т. Д. Часть этого кода - моя, часть - чужая.

Проблема: Когда нижеприведенный шаблон вызывается с шаблонамиНиже описано, что все узлы xsl:text после теста if выводятся в виде строки вместо узла HTML, поэтому значок не отображается.

Этот вопрос связан с пониманием почему? того, что происходит.Мой точный вопрос находится внизу этого поста.

Итак, у меня есть шаблон, который я называю, который генерирует элементы SVG с элементом <use> для использования со спрайтом SVG.

<xsl:template name="svg-link">

  <xsl:param name="svg-id"/>
  <xsl:param name="svg-class"/>
  <xsl:param name="svg-title"/>

  <span class="{$svg-class} svgstore svgstore--{$svg-loc}">
    <svg>
      <xsl:if test="$svg-title != ''">
        <title><xsl:value-of select="$svg-title"/></title>
      </xsl:if>
      <xsl:text disable-output-escaping="yes">&lt;use xlink:href="</xsl:text>
      <xsl:value-of select="concat('#', $svg-loc)" />
      <xsl:text disable-output-escaping="yes">"&gt;&lt;/use&gt;</xsl:text>
    </svg>
  </span>

</xsl:template>

Все виды шаблонов вызывают / применяют этот шаблон.В частности, есть одна проблема, с которой я столкнулся.У нас есть два фрагмента, реализованных CMS, которые выводят одну и ту же разметку, но конфигурации для фрагментов реализованы по-разному, то есть шаблон страницы A и шаблон страницы B. Рассматриваемый фрагмент состоит из нескольких шаблонов XSL.Шаблоны организованы так:

  • Шаблон фрагмента: точка входа для фрагмента для всех вызывающих абонентов.Принимает несколько параметров, связанных с классами CSS.Создает несколько элементов оболочки для фрагмента.Вызывает следующий шаблон.
  • Шаблон «Модель»: - это шаблон, который должен быть определен каждым шаблоном страницы.Как упоминалось выше, каждый шаблон страницы использует свой подход к реализации параметров конфигурации для фрагмента.Идея состоит в том, чтобы сделать следующий шаблон независимым от того, как был изначально сконфигурирован сниппет, потому что этот шаблон отвечает за знание этих деталей и передачу его следующему шаблону.
  • Шаблон элемента сниппета: отображает большую часть разметки для фрагмента на основе информации, передаваемой ему шаблоном "Model" .

Вот несколько упрощенных псевдокодов, демонстрируемых выше:

<xsl:template name="snippet">

  <xsl:param name="outer-classes"/>
  <xsl:param name="inner-classes"/>

  <xsl:variable name="items">
    <xsl:call-template name="snippet-model"/>
  </xsl:variable>

  <!-- Render Snippet if it has content. -->
  <xsl:if test="count( $items )">
    <div class="{ $outer-classes }">
      <div class="{ $inner-classes }">
        <xsl:copy-of select="$items">
      </div>
    </div>
  </xsl:if>

</xsl:template>

<!-- Placeholder. Defined by each page template. -->
<xsl:template name="snippet-model"/>

<xsl:template name="snippet-item">

  <xsl:param name="a"/>
  <xsl:param name="b"/>
  <xsl:param name="b"/>

  <div class="snippet-item {$a}">

    <xsl:apply-templates select="$b"/>

    <xsl:call-template name="svg-link">
      <xsl:with-param name="svg-id">alpha</xsl:with-param>
      <xsl:with-param name="svg-class">alpha</xsl:with-param>
      <xsl:with-param name="svg-title">The Title</xsl:with-param>
    </xsl:call-template>
  </div>

</xsl:template>

И пример того, как шаблон страницы использует приведенное выше:

<xsl:template match="table[@class = 'snippet-alpha']">

  <xsl:call-template="snippet">
    <xsl:with-param name="outer-classes">page-template-a other</xsl:with-param>
    <xsl:with-param name="inner-classes">some-template-modifier</xsl:with-param>
  </xsl:call-template>

</xsl:template>

<!-- Template definition of `snippet-model` template. -->
<xsl:template name="snippet-model">

  <!-- Another page template might not use `tbody/tr` to loop over. -->
  <xsl:for-each select="tbody/tr">
    <xsl:call-template="snippet-item">
      <xsl:with-param name="a" select="td[1]"/>
      <xsl:with-param name="b" select="td[2]"/>
      <xsl:with-param name="c" select="td[3]"/>
    </xsl:call-template>
  </xsl:for-each>

</xsl:template>

Я сузил свою проблему до вероятности xsl:variable захвата результатов xsl:call-templateв шаблоне snippet.И / или ссылка на эту переменную позже с xsl:copy-of.

Что я пробовал?

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

  • Работает: Добавление xmlns:xlink="http://www.w3.org/1999/xlink" в xsl:stylesheet для файла, который содержитsvg-link шаблон, а затем моддинг svg-link шаблон, см. Код под этим списком.
  • Работает: Вместо вывода значения xsl:variable, которое фиксирует результаты xsl:call-template с xsl:copy-of.Я заменяю xsl:copy-of вторым xsl:call-template, идентичным вызову, который был сделан внутри переменной.
  • Не работает: Используется xsl:sequence вместо xsl:copy-of.
  • Не работает: Пробный ввод данных (?) xsl:variable, который фиксирует результаты xsl:call-template с атрибутом as.Т.е. as="node()*".
<xsl:template name="svg-link">

  <xsl:param name="svg-id"/>
  <xsl:param name="svg-class"/>
  <xsl:param name="svg-title"/>

  <span class="{$svg-class} svgstore svgstore--{$svg-loc}">
    <svg>
      <xsl:if test="$svg-title != ''">
        <title><xsl:value-of select="$svg-title"/></title>
      </xsl:if>
      <use xlink:href="{concat( '#', $svg-loc )}"></use>
    </svg>
  </span>

</xsl:template>

Вопрос: Почему часть содержимого шаблона svg-link выводится в виде строки (вместо HTML) в зависимости от того, какрезультат вызова xsl:call-template фиксируется / вызывается?Как видите, у меня есть работающие и нерабочие решения - я хотел бы знать, почему.Спасибо! * * 1092

1 Ответ

1 голос
/ 03 мая 2019

Прежде всего, disable-output-escaping является дополнительной функцией сериализации. Кроме того, спецификации XSLT 2 или 3 прописаны, когда они вообще не работают, см. https://www.w3.org/TR/xslt-30/#disable-output-escaping

Если выходной выход отключен для xsl:value-of или xsl:text инструкция оценивается, когда действует временное состояние вывода, запрос на отключение экранирования вывода игнорируется.

и https://www.w3.org/TR/xslt-30/#dt-temporary-output-state

xsl: переменная, xsl: параметр, xsl: с-параметр, xsl: функция, xsl: ключ, xsl: sort, xsl: аккумулятор-правило и xsl: merge-key всегда оценивают инструкции в их конструкторе последовательности во временном состояние вывода

Так внутри вашего xsl:variable любой disable-output-escaping не может работать.

Вся попытка использовать его для создания элемента SVG use совершенно не нужна, вы можете создавать любые элементы результата как буквальные элементы результата, например, <use xlink:href="{concat( '#', $svg-loc )}"></use> (с соответствующей декларацией пространства имен XLink для атрибута из этого пространства имен) или, если вам нужно вычислить часть имени или пространства имен, с помощью xsl:element.

...