Невозможно заставить xslt выводить (&) даже после экранирования символа

Я пытаюсь создать строку запроса для присвоений переменных, разделенных символом & (например: "var1=x&var2=y&..."). Я планирую передать эту строку во встроенный флеш-файл.

У меня проблемы с отображением символа & в XSLT. Если я просто наберу & без тегов, возникнет проблема с отображением документа XSLT. Если я наберу &amp; без тегов вокруг него, то документ на выходе будет &amp; без изменений. Если я наберу <xsl:value-of select="&" /> или <xsl:value-of select="&amp;" />, я также получу сообщение об ошибке. Это возможно? Примечание. Я также пробовал &amp;amp;, но безуспешно.


person Community    schedule 15.09.2008    source источник
comment
Какая четвертая метка этого вопроса? Я просто думаю, что это должно быть озвучено пользователем ...   -  person Thomas Owens    schedule 16.09.2008
comment
два пробела в конце, казалось, сделали второе пространство собственным тегом.   -  person grapefrukt    schedule 16.09.2008
comment
@DimitreNovatchev Действительно, это исчерпывающий ответ и многое другое. Попробую на работе.   -  person Grim    schedule 13.10.2015
comment
Как вы выводите? <xsl:output method="text"/> или <xsl:output method="xml"/>?   -  person Flynn1179    schedule 15.10.2015


Ответы (13)


Вы можете комбинировать disable-output-escaping с CDATA разделом. Попробуй это:

<xsl:text disable-output-escaping="yes"><![CDATA[&]]></xsl:text>
person Kevin Hakanson    schedule 26.09.2008

Я пытаюсь создать строку запроса для присвоений переменных, разделенных символом & (например: "var1=x&var2=y&..."). Я планирую передать эту строку во встроенный флеш-файл.

У меня проблемы с отображением символа & в XSLT.

Вот работающая, короткая и полная демонстрация того, как создать такой URL:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:variable name="vX" select="'x'"/>
 <xsl:variable name="vY" select="'y'"/>
 <xsl:variable name="vZ" select="'z'"/>

  <xsl:template match="/">
    <xsl:value-of select=
"concat('http://www.myUrl.com/?vA=a&amp;vX=', $vX, '&amp;vY=', $vY, '&amp;vZ=', $vZ)"/>
  </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к любому исходному XML-документу (игнорируется):

<t/>

Получен желаемый правильный результат:

http://www.myUrl.com/?vA=a&vX=x&vY=y&vZ=z

Что касается других вопросов, поднятых в вопросе:

Если я наберу &amp; без тегов вокруг него, то документ на выходе будет &amp; без изменений.

Вышеупомянутое утверждение просто неверно ... Просто запустите приведенное выше преобразование и посмотрите на результат.

Что происходит на самом деле:

Результат, который вы видите, абсолютно правильный, однако ваш метод вывода - html или xml (значение по умолчанию для method=), поэтому сериализатор процессора XSLT должен представлять правильный результат - строку http://www.myUrl.com/?vA=a&vX=x&vY=y&vZ=z - как (часть) текстовый узел в правильно сформированном XML-документе или в HTML-дереве.

По определению в правильно сформированном XML-документе буквальный амперсанд должен быть экранирован символьной ссылкой, такой как встроенный &amp;, &#38; или &#x26;

Помните: строка, представленная как (часть) текстового узла XML или в дереве HTML, может не выглядеть как та же строка, когда представлена ​​как текст. Тем не менее, это два разных представления одной и той же строки.

Чтобы лучше понять этот простой факт, сделайте следующее:

Возьмите указанное выше преобразование и замените объявление xsl:output:

 <xsl:output method="text"/>

с этим:

 <xsl:output method="xml"/>

Кроме того, заключите вывод в один элемент XML. Вы также можете попробовать использовать разные escape-последовательности для амперсанда. Трансформация теперь может выглядеть так:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" method="xml"/>

 <xsl:variable name="vX" select="'x'"/>
 <xsl:variable name="vY" select="'y'"/>
 <xsl:variable name="vZ" select="'z'"/>

  <xsl:template match="/">
        <t>
            <xsl:value-of select=
 "concat('http://www.myUrl.com/?vA=a&amp;vX=', $vX, '&#38;vY=', $vY, '&#x26;vZ=', $vZ)"/>
        </t>
  </xsl:template>
</xsl:stylesheet>

И результат:

<t>http://www.myUrl.com/?vA=a&amp;vX=x&amp;vY=y&amp;vZ=z</t>

Вы получите тот же результат с методом вывода html.

Вопрос:

Является ли выводимый URL-адрес отличным (или даже "поврежденным") от того, который был выведен при первом преобразовании?

Ответ:

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

Вопрос:

Должен ли я использовать атрибут DOE (disable-output-escaping="yes") для вывода желаемого URL-адреса?

Ответ:

Нет, как показано в первом преобразовании.

Вопрос:

Рекомендуется ли использовать атрибут DOE (disable-output-escaping="yes") для вывода желаемого URL-адреса?

Ответ:

Нет, использование DOE - плохая практика в XSLT и обычно сигнал о том, что программист плохо разбирается в модели обработки XSLT. Кроме того, DOE - это только дополнительная функция XSLT 1.0, и возможно, что ваш XSLT-процессор не реализует DOE, или даже если он это делает, у вас могут возникнуть проблемы с выполнением того же преобразования с другим XSLT-процессором.

Вопрос

Я пришел от другой проблемы к вопросу, за который назначил вознаграждение. Моя проблема: я пытаюсь создать этот метод onclick:

    <input type="submit" 
onClick="return confirm('are you sure?') && confirm('seriously?');" />

что я могу сделать, так это: я могу разместить подтверждения в функции ... но меня беспокоит то, что я не могу создать & внутри атрибута! Думаю, решение этого вопроса - это решение моей проблемы.

Ответ

Фактически, вы можете указать логическую операцию && внутри выражения JavaScript внутри атрибута, представив ее как &amp;&amp;

Вот полный пример, который может запустить каждый, как и я, в трех браузерах: Chrome, Firefox 41.1.01 и IE11:

HTML:

<!DOCTYPE html> 

    <html> 
      <head> 
        <link rel="stylesheet" href="style.css"> 
        <script src="script.js"></script> 
      </head> 
      <body> 
        <h1>Hello Plunker!</h1> 
        <input type="submit" 
onClick="alert(confirm('are you sure?') &amp;&amp; confirm('seriously?'));" /> 
      </body> 
    </html>

JavaScript (script.js):

function confirm(message) { 
  alert(message); 
  return message === 'are you sure?'; 

}

Когда вы запустите это, вы сначала получите следующее предупреждение:

введите описание изображения здесь

Затем, нажав кнопку OK, вы получите второе предупреждение:

введите описание изображения здесь

И после нажатия OK вы, наконец, получите предупреждение о результате && операции:

введите описание изображения здесь

Вы можете поиграть с этим кодом, варьируя значения аргументов, передаваемых функции confirm(), и вы убедитесь, что полученные результаты соответствуют результатам использования оператора &&.

Например, если вы измените элемент <input> на этот:

<input type="submit" 
onClick="alert(confirm('really sure?') &amp;&amp; confirm('seriously?'));" /> 

Сначала вы получите это предупреждение:

введите описание изображения здесь

И когда вы нажмете OK, вы сразу получите окончательный результат && операции:

введите описание изображения здесь

Второе предупреждение пропускается, потому что 1-й операнд операции && был false, а JavaScript сокращает &&, где 1-й операнд - false.

Подводя итог:

Оператор && внутри атрибута в документе HTML, созданном с помощью XSLT, легко использовать, указав операнд && как &amp;&amp;

person Dimitre Novatchev    schedule 13.10.2015
comment
Пробовал, сеть транспортирует a вместо & - person Grim; 15.10.2015
comment
Я пришел от другой проблемы к вопросу, за который назначил вознаграждение. Моя проблема: я пытаюсь создать этот метод onclick: <input type="submit" onClick="return confirm('are you sure?') && confirm('seriously?');" /> я могу сделать следующее: я могу разместить подтверждения в функции ... но меня беспокоит, что я не могу сделать & внутри атрибута! Думаю, решение этого вопроса - это решение моей проблемы. - person Grim; 15.10.2015
comment
@PeterRader, просто используйте: <input type="submit" onClick="return confirm('are you sure?') &amp;&amp; confirm('seriously?');" /> - легко проверить, что значение атрибута onClick в точности соответствует нужной строке. Просто запустите это преобразование: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/*"> <xsl:value-of select="@onClick"/> </xsl:template> </xsl:stylesheet> против этого XML-документа: <input type="submit" onClick="return confirm('are you sure?') &amp;&amp; confirm('seriously?');" /> - person Dimitre Novatchev; 16.10.2015
comment
Javascript сообщает мне, что amp не определен. - person Grim; 16.10.2015
comment
@PeterRader Вы всегда можете прибегнуть к законам ДеМоргана - используйте onclick="return !(!confirm('are you sure?') || !confirm('seriously?'));". Не о чем & беспокоиться :) - person Flynn1179; 16.10.2015
comment
@PeterRader, у меня есть доказательство. Я определил и запустил это в plncr: <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> </head> <body> <h1>Hello Plunker!</h1> <input type="submit" onClick="alert(confirm('are you sure?') &amp;&amp; confirm('seriously?'));" /> </body> </html> И при нажатии кнопки alert() правильно отображает: false. Сам JS: function confirm(message) { alert(message); return message === 'are you sure?'; } Итак, в использовании встроенной ссылки &amp; нет ничего плохого. - person Dimitre Novatchev; 16.10.2015
comment
@PeterRader, Продолжение пред. комментарий: И я поиграл, установив функцию js для возврата false или true - во всех случаях правильный результат логической операции был получен с помощью alert(). Попробуйте сами, и вы увидите. Заключение: давайте раз и навсегда довести этот аргумент до его истинного заключения. - person Dimitre Novatchev; 16.10.2015
comment
@DimitreNovatchev какой браузер вы используете? - person Grim; 16.10.2015
comment
@PeterRader, в данном случае Chrome, но я могу протестировать также с IE11 и Firefox - просто нужно 5 часов, чтобы вернуться домой с работы - person Dimitre Novatchev; 16.10.2015
comment
@PeterRader, Да, я успешно запустил один и тот же пример как с IE11, так и с FireFox 41.0.1. Я рад, что теперь у вас есть рабочие примеры, как указать логическую операцию && внутри атрибута html, сгенерированного XSLT. Похоже, это полностью отвечает на ваш вопрос, или нет? - person Dimitre Novatchev; 17.10.2015
comment
@PeterRader, я обновил ответ, и он полностью показывает, как указать оператор && внутри атрибута элемента HTML-документа, созданного XSLT. Решает ли это вашу проблему? - person Dimitre Novatchev; 17.10.2015
comment
@PeterRader: Вообще говоря, когда вы встраиваете фрагменты одного языка в другой, вы должны применять экранирование на каждом уровне. Строка в JavaScript в атрибуте HTML onclick в строке PHP является типичным примером. Кавычки внутри строки должны быть экранированы, чтобы сформировать правильную строку JavaScript. Весь фрагмент JavaScript должен быть экранирован (PHP htmlspecialchars()), чтобы быть встроенным в атрибут HTML. И HTML должен быть дополнительно экранирован, чтобы быть встроенным в строку PHP (обратная косая черта, кавычки,…). Димитр прав в том, что вам следует избегать & в атрибуте onclick. - person Palec; 17.10.2015

Вы выражаете URI в HTML или XHTML? например <tag attr="http://foo.bar/?key=value&amp;key2=value2&amp;..."/> Если это так, то "&amp;" - это правильный способ выразить амперсанд в значении атрибута, даже если он выглядит иначе, чем буквальный URI, который вы хотите. Браузеры будут декодировать «&amp;» и любую другую ссылку на символьный объект перед их загрузкой или передачей во Flash. Встраивать буквальный, одиночный "&" непосредственно в HTML или XHTML некорректно.

Я также лично рекомендую больше узнать об XML, чтобы более четко осмыслить подобные вещи. Например, попробуйте больше использовать W3C DOM (для большего, чем просто тривиальный Javascript); Даже если вы не используете его изо дня в день, изучение DOM помогло мне правильно подумать о древовидной структуре XML и о том, как правильно кодировать атрибуты и элементы.

person user4010    schedule 15.09.2008

Используйте disable-output-escaping="yes" в своем теге value-of

person Thunder3    schedule 15.09.2008

Если вы создаете строку запроса как часть более крупного URL-адреса в атрибуте какого-либо другого тега (например, "embed"), тогда вы на самом деле хотите экранировать & как. Хотя все браузеры поймут, что вы имеете в виду, и сделайте то, что нужно, если вы передадите сгенерированный документ валидатору, он пометит неэкранированный & в значении атрибута.

person rjray    schedule 15.09.2008

Если вы пытаетесь создать XML-файл в качестве вывода, вы захотите создать &amp; (поскольку & сам по себе является недопустимым XML). Если вы просто создаете строку, вам следует установить режим вывода таблицы стилей на text, включив следующее в качестве дочернего элемента xsl:stylesheet

<xsl:output method="text"/>

Это предотвратит экранирование элементов в таблице стилей, и <xsl:value-of select="'&amp;'" /> должен выдать &.

person ashirley    schedule 16.09.2008

Если ваше преобразование генерирует XML-документ, вам не следует отключать экранирование вывода. Вы хотите экранировать символы разметки в выводе, чтобы не генерировать искаженный XML. XML-объект, с помощью которого вы обрабатываете вывод (например, DOM), отключит экранирование текста за вас.

Если вы используете строковые манипуляции вместо XML-объекта для обработки вывода, у вас есть проблема. Но проблема не в вашем XSLT, а в решении использовать строковые манипуляции для обработки XML, что почти всегда плохо.

Если ваше преобразование генерирует HTML или текст (и вы установили тип вывода для элемента <xsl:output>, верно?), Это другая история. Тогда уместно использовать disable-output-escaping='yes' в вашем <xsl:value-of> элементе.

Но в любом случае вам нужно экранировать символы разметки в текстовых узлах XSLT, если вы не заключили текст в раздел CDATA.

person Robert Rossney    schedule 08.10.2008

Отключить экранирование вывода выполнит свою работу ... поскольку этот атрибут поддерживается только для текста, вы также можете управлять шаблоном, например:

 <xsl:variable name="replaced">

    <xsl:call-template name='app'>
      <xsl:with-param name='name'/>       
    </xsl:call-template>
  </xsl:variable>


<xsl:value-of select="$replaced" disable-output-escaping="yes"/>

---> Обернул вызов шаблона в переменную и использовал disable-output-escaping = "yes" ..

person Taran    schedule 03.06.2014

Просто замените & на

<![CDATA[&]]>

в данных. EX: данные XML

<title>Empire <![CDATA[&]]> Burlesque</title>

Тег XSLT:

<xsl:value-of select="title" />

Продукт: Empire & Burlesque.

person Ram    schedule 16.02.2016

Обратите внимание, что вы можете использовать disable-output-escaping внутри значения узла или строки / текста, например:

<xsl:value-of select="/node/here" disable-output-escaping="yes" />

or

<xsl:value-of select="'&amp;'" disable-output-escaping="yes" />
<xsl:text disable-output-escaping="yes">Texas A&amp;M</xsl:text>

Обратите внимание на одинарные кавычки в xsl: value-of.

Однако вы не можете использовать disable-output-escaping для атрибутов. Я знаю, что это полностью запутано, но так обстоит дело в XSLT 1.0. Таким образом, следующее НЕ будет работать:

<xsl:value-of select="/node/here/@ttribute" disable-output-escaping="yes" />

Потому что мелким шрифтом цитата:

Таким образом, отключение экранирования вывода для элемента <xsl:value-of /> или <xsl:text />, который используется для генерации строкового значения комментария, инструкции обработки или атрибута, является ошибкой. узел;

курсив мой.

Взято с сайта: http://www.w3.org/TR/xslt#disable-output-escaping

person Community    schedule 17.09.2008
comment
Это не совсем так. Вы можете использовать disable-output-escaping при передаче значения атрибута в исходном дереве, скажем, текстовому узлу. Ваш пример будет работать, если он не находится внутри элемента ‹xsl: attribute› или шаблона значения атрибута. - person Robert Rossney; 08.10.2008
comment
<xsl:value-of select="/node/here/@ttribute" disable-output-escaping="yes" /> это не пример того, что описано в цитате. Вы читаете атрибут, а не записываете его. - person bluish; 14.10.2011

Использование атрибута disable-output-escaping (логического), вероятно, самый простой способ добиться этого. Обратите внимание, что вы можете использовать это не только с <xsl:value-of/>, но и с <xsl:text>, что может быть чище, в зависимости от вашего конкретного случая.

Вот соответствующая часть спецификации: http://www.w3.org/TR/xslt#disable-output-escaping

person tomasr    schedule 15.09.2008

org.apache.xalan.xslt.Process, версия 2.7.2 выводит сообщение «Вот работающая, короткая и полная демонстрация того, как создать такой URL», упомянутую выше:

<?xml version="1.0" encoding="UTF-8"?>http://www.myUrl.com/?vA=a&amp;vX=x&amp;vY=y&amp;vZ=z11522

Объявление XML подавляется дополнительным omit-xml-declaration="yes", но, тем не менее, с выходом method="text" экранирование амперсандов не оправдано.

person Peter Dolland    schedule 25.01.2019
comment
Хорошо, я вижу, что у xalan есть дополнительный переключатель -TEXT для форматирования текста. В этом случае результат будет таким, как описано выше. - person Peter Dolland; 25.01.2019

попробуйте: ‹xsl: value-of select =" "disable-output-escaping =" yes "/>

Извините, если форматирование испортилось.

person Jim Lynn    schedule 15.09.2008