Включить узлы HTML в <xsl: attribute>
Я хочу включить HTML в атрибут элемента (для атрибута очистки данных, используемого здесь: http://foundation.zurb.com/docs/components/clearing.html). мой <caption>
Данные доступны двумя способами:
<caption mode="formatted">
<p>A fairly long looking <a href="http://www.stackru.com">caption with a link</a> that goes to an external site.</p>
</caption>
<caption mode="unformatted">
<![CDATA[A fairly long looking <a href="http://www.stackru.com">caption with a link</a> that goes to an external site.]]>
</caption>
Вот мой шаблон:
<xsl:template match="images/entry">
<!-- process contents of caption node-->
<xsl:variable name="cap">
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:apply-templates select="caption/*" mode="html" />
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:variable>
<li>
<xsl:copy-of select="$cap"/> //outside of attribute it works
<img>
<xsl:attribute name="src">/image/2/150/112/5<xsl:value-of select="@path"/>/<xsl:value-of select="filename"/></xsl:attribute>
<xsl:attribute name="data-caption">
<xsl:copy-of select="$cap"/> //inside of attribute it removes the <a> tag
</xsl:attribute>
</img>
</li>
</xsl:template>
mode=html
соответствует <a>
тег в <caption>
узел с этим шаблоном:
<!-- mark external links -->
<xsl:template match="a" mode="html">
<a href="{@href}" title="{@title}">
<xsl:if test="number(substring(@href,1,4)='http')">
<xsl:attribute name="class">external</xsl:attribute>
<xsl:attribute name="target">_blank</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="* | @* | text()" mode="html"/>
</a>
</xsl:template>
Если я использую "неотформатированную" подпись, она сохраняет <a>
тег (желаемое поведение). Однако, когда я использую эту подпись, я не могу использовать шаблон "пометить внешние ссылки", чтобы исправить <a>
тег. Используя "отформатированный" заголовок, я могу обработать <a>
тег, как я хочу, но он теряется, когда я использую xsl:copy-of
внутри <img>
<xsl:attribute>
, Он будет отображаться нормально вне атрибута, например так:
<![CDATA[<p>A fairly long looking <a href="http://www.stackru.com" title="" class="external" target="_blank">caption with a link</a> that goes to an external site.</p>]]>
Есть ли способ, чтобы мой конечный результат выглядел так:
<img src="/image/2/150/112/5/images/my-image.jpg"
data-caption="<![CDATA[A fairly long looking <a class="external" target="_blank" href="http://www.stackru.com">caption with a link</a> that goes to an external site.]]>;" />
Спасибо за прочтение.
1 ответ
Во-первых, давайте проясним, что вы не включаете "узлы" в свои атрибуты; вам нужно сериализовать атрибут, содержащий разметку XML. Мы говорим на лексическом уровне, а не на уровне дерева, а узлы существуют только на уровне дерева.
Чтобы получить этот результат, есть две проблемы. Во-первых, вам нужно создать строку, содержащую лексический XML, а затем передать эту строку в качестве значения атрибута. Во-вторых, вам нужно предотвратить экранирование специальных символов в этой строке.
Для первой проблемы есть два подхода: вы можете вызвать внешнюю функцию serialize(), которая преобразует дерево в лексический XML в виде строки, например, saxon:serialize(), если вы используете Saxon, или вы можете написать свой собственный (что не сложно для простых случаев, и это уже было сделано - Дэвид Карлайл (David Carlisle) написал полный сериализатор XML на XSLT).
Вторая проблема сложна. Спецификация сериализации XSLT (все версии) непреклонна, что метод сериализации HTML не должен экранировать "<", появляющийся в значениях атрибутов, но он почти или ничего не говорит о ">". Саксонский избегает ">" как ">"
Якобы потому, что это требуется в старых браузерах (возможно, уже очень старых), но я не думаю, что это требуется спецификацией, и другие процессоры могут отличаться. Disable-output-escaping не работает для значений атрибутов, поэтому вам, возможно, придется прибегнуть к созданию всей сериализации элемента вручную, используя disable-output-escaping. Кроме того, в XSLT 2.0 вы можете использовать карты символов для принудительного вывода ">" в значении атрибута.
В вашем примере кода вы используете disable-output-escaping при записи значения переменной. В спецификации есть история йойо. В сообщении об ошибке XSLT 1.0 (так называемое исправление "липкая точка") сказано, что это разрешено, но в XSLT 2.0 это было отменено, поскольку это было несовместимо с разрешением полного навигационного доступа к фрагментам результирующего дерева, содержащимся в переменных. Таким образом, суть в том, что он может или не может работать в зависимости от процессора, который вы используете - но, конечно, это верно для отключения-вывода-выхода в целом.
Совершенно другое решение этого требования может заключаться в выводе чего-то другого - например, с использованием шевронов вместо угловых скобок - и затем фильтрации сериализованного вывода через текстовый фильтр, который заменяет соответствующие символы теми, которые вы на самом деле хотите.