Pull to refresh

Решение проблем обработки XSLT на стороне клиента (часть 2)

Reading time5 min
Views8.3K
В прошлой статье я описал как реализовать инклудинг и кеширование при обработке xsl-темплейтов на стороне клиента. Сегодня я раскажу с помощью каких инструментов можно проводить отладку xslt-преобразований на стороне клиента и о работе конструкции <xsl:value-of select=«xxx» disable-output-escaping=«yes»/> в firefox.

Отладка XSLT на клиенте


Во время обработки xsl-документов в браузере могут происходить различные ошибки:
1) сетевые ошибки — когда xml или xsl данные не были получены;
2) ошибки обработки шаблонов.

Сетевые ошибки

Для контроля сетевых ошибок можно использовать отладочные средства браузеров. Все отладочные средства firebug (firefox), dragonfly (opera) и devtools (chrome) могут показать какие ресурсы были загружены из сети непосредственно ассинхронным запросом. Например, если мы обрабатываем данные in_data.xml с помощью шаблона first.xsl, то загрузку этих данных мы сможем проконтролировать
— раздел «net» в firebug
— раздел «net» в dragonfly
— раздел «resources» в devtools.

Иначе дело обстоит если для успешной обработки нужно подгрузить дополнительный xsl-файл (инклуд). В этом случае firebug (firefox) не покажет, что что-то было загружено.


А интегрированные среды дебагинга dragonfly (opera) и devtools (chrome) покажут какие дополнительные xsl файлы были подгружены.



Ошибки обработки шаблонов

Если во время обработки шаблона произошла ошибка, то её можно отловить и вывести в удобном для вас виде. Мне удобно во время разработки скидывать такие сообщения в консоль firebug'а
jQuery('#id_div').transform(
{ xml:'res/1.xml',
 xsl:'res/1.xsl',
 success:function (){
  jQuery('#id_info').html('готово');    
 },
 error:function (xml_data, xsl_data, success, cur_obj, error){
  console.log('xml: '+xml_data);
  console.log('xsl: '+xsl_data);
  console.log('success: '+success);         
  console.log('cur_obj:');console.log(cur_obj);
  console.log('error:');console.log(error);
 }
});


* This source code was highlighted with Source Code Highlighter.

В этом случае вывод ошибки будет примерно таким:

Событие «error» будет вызвано в случае возникновения ошибки. В функцию события будет передано несколько параметров, основной из которых — error — собстенно описание ошибки.

disable-output-escaping=«yes» в firefox


Описание проблемы

В некоторых случаях в xml-данных могут приходить целые куски отформатированного html, в этих случаях эти куски нужно вставлять в конечный документ без изменений, то есть «как есть». Например это могут быть данные, содержащие результаты поиска, в которых искомое слово выделенно жирным («мы <b>искали</b> все возможные решения»). Сделать простую замену текста средствами xslt можно, но того не стоит (попробуйте как-нибудь на досуге заняться этим). Поэтому проще передавать уже отформатированный текст. Опытный программист придумает ещё массу примеров. Для вставки данных без экранирования в xslt есть специальный атрибут disable-output-escaping, который необходимо установить в «yes». Выглядит это так
<xsl:value-of select="xxx" disable-output-escaping="yes"/>

* This source code was highlighted with Source Code Highlighter.

Но в firefox, начиная самой первой версией и заканчивая всей третьей веткой (в firefox 4 не тестировал), не полная реализация xsl-процессора. Их xsl-процессор, который индентифицирует себя как «Transformiix», не обрабатывает disable-output-escaping=«yes». Этой ошибке уже много лет https://bugzilla.mozilla.org/show_bug.cgi?id=98168 и недавно мы «отмечали» 9-летие этой баги. Там же по ссылке написаны оправдания команды firefox, которые можно свести к одному — там много работы, если хотите правьте сами.

Решение проблемы

Существует такое решение проблемы — использовать вместо конструкции <xsl:value-of select=«xxx» disable-output-escaping=«yes»/> вызов <xsl:copy-of select=«xxx»/>. Но в этом случае мы не можем передать в узле xxx данные в виде
<xxx>Резельтат поиска <![CDATA[<i>"первый"</i>]]></xxx>

* This source code was highlighted with Source Code Highlighter.

а придётся передавать данные так
<xxx>Резельтат поиска <i>"первый"</i></xxx>

* This source code was highlighted with Source Code Highlighter.

то есть это будет уже не совсем верный xml-файл. И тогда мы получаем проблему в остальных браузерах, где такое решение работать уже не будет.

Другое решение проблемы

Я решил использовать другой подход. Использовать специальный фикс, написанный на javascript.

1. Вместо привычного <xsl:value-of select="xxx" disable-output-escaping="yes"/> в наших шаблонах придётся использовать вызов
<xsl:call-template name="inc_disable_output_escaping"><xsl:with-param name="param" select="xxx"/></xsl:call-template>

* This source code was highlighted with Source Code Highlighter.


Где темплейт inc_disable_output_escaping выглядит так:
<xsl:template name="inc_disable_output_escaping">
  <xsl:param name="param"></xsl:param>
  <xsl:choose>
   <xsl:when test="system-property('xsl:vendor')='Transformiix'">
    <!-- костыль для firefox -->
    <div style="display:none" class="fix_ff_disable_output_escaping"><xsl:value-of select="$param" disable-output-escaping="yes"/></div>
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of select="$param" disable-output-escaping="yes"/>
   </xsl:otherwise>
  </xsl:choose>  
</xsl:template>


* This source code was highlighted with Source Code Highlighter.

В этом темплейте по имени xsl-процессора (xsl:vendor) мы выведем данные стандартной конструкцией с disable-output-escaping=«yes», а в случае xsl-процессора от firefox'а данные вставим в невидимый контейнер так, как firefox эти данные может вставить, то есть в экранированном виде.
А потом, после успешного преобразования, и обновления DOM документа, мы перекодируем данные в этих контейнерах на правильные и вставим их на место этих контейнеров.
function fix_ff_disable_output_escaping() {
  jQuery('div.fix_ff_disable_output_escaping').each(
  function(i, obj){
   var j_obj=jQuery(obj);
   j_obj.replaceWith(Encoder.htmlDecode(j_obj.html()));
  }
 )
}


* This source code was highlighted with Source Code Highlighter.

Для декодирования html-мнемоник используется функция htmlDecode js-библиотеки Encoder.

Пример работы данной техники и архив с решением можно взять тут ra-project.net/xsl_tests/test2.html

PS Не забывайте отправлять правильный content-type для xml/xsl документов. А именно «Content-type: text/xml».
Tags:
Hubs:
+5
Comments11

Articles