#xml #xslt #escaping #invalid-characters
Вопрос:
Я пытаюсь создать строку запроса с назначениями переменных, разделенных amp;
символом (например: "var1=xamp;var2=yamp;..."
). Я планирую передать эту строку во встроенный флэш-файл.
У меня возникли проблемы amp;
с отображением символа в XSLT. Если я просто наберу amp;
текст без тегов, возникнет проблема с отображением документа XSLT. Если я наберу amp;amp;
текст без тегов вокруг него, то вывод документа будет amp;amp;
без изменений. Если я наберу <xsl:value-of select="amp;" />
или <xsl:value-of select="amp;amp;" />
я также получу ошибку. Возможно ли это? Примечание: Я тоже пытался amp;amp;amp;
, но безуспешно.
Комментарии:
1. Каков 4-й тег этого вопроса? Я просто думаю, что это должно быть выбрано пользователем…
2. два пробела в конце, казалось, делали второе пространство своим собственным тегом.
3. @DimitreNovatchev Действительно, это исчерпывающий ответ и многое другое. Я попробую это на работе.
4. Как вы выводите данные?
<xsl:output method="text"/>
или<xsl:output method="xml"/>
?
Ответ №1:
Вы можете объединить disable-output-escaping
с CDATA
разделом. Попробуйте это:
<xsl:text disable-output-escaping="yes"><![CDATA[amp;]]></xsl:text>
Ответ №2:
Я пытаюсь создать строку запроса с назначениями переменных, разделенных
amp;
символом (например:"var1=xamp;var2=yamp;..."
). Я планирую передать эту строку во встроенный флэш-файл.У меня возникли проблемы
amp;
с отображением символа в 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=aamp;amp;vX=', $vX, 'amp;amp;vY=', $vY, 'amp;amp;vZ=', $vZ)"/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование применяется к любому исходному XML-документу (игнорируется):
<t/>
получен желаемый, правильный результат:
http://www.myUrl.com/?vA=aamp;vX=xamp;vY=yamp;vZ=z
Что касается других вопросов, поднятых в этом вопросе:
Если я наберу
amp;amp;
текст без тегов вокруг него, то вывод документа будетamp;amp;
без изменений.
Приведенное выше утверждение просто неверно … Просто запустите приведенное выше преобразование и посмотрите на результат.
Что на самом деле происходит:
Результат, который вы видите, абсолютно правильный, однако ваш метод вывода- html
или xml
(значение по умолчанию method=
), поэтому сериализатор процессора XSLT должен представлять правильный результат-строку http://www.myUrl.com/?vA=aamp;vX=xamp;vY=yamp;vZ=z
-как (часть) текстового узла в правильно сформированном XML-документе или в дереве HTML.
По определению в правильно сформированном XML-документе литеральный амперсанд должен быть экранирован ссылкой на символ, такой как встроенный amp;amp;
или amp;#38;
, или amp;#x26;
Помните: строка, представленная как (часть) текстового узла XML или в дереве HTML, может выглядеть не так, как строка, представленная в виде текста. Тем не менее, это два разных представления одной и той же строки.
Чтобы лучше понять этот простой факт, сделайте следующее:
Выполните приведенное выше преобразование и замените xsl:output
декларацию:
<xsl:output method="text"/>
с этим одним:
<xsl:output method="xml"/>
Also, surround the output in a single XML element. You may also try to use different escapes for the ampersand. The transformation may now look like this:
<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=aamp;amp;vX=', $vX, 'amp;#38;vY=', $vY, 'amp;#x26;vZ=', $vZ)"/>
</t>
</xsl:template>
</xsl:stylesheet>
And the result is:
<t>http://www.myUrl.com/?vA=aamp;amp;vX=xamp;amp;vY=yamp;amp;vZ=z</t>
You will get the same result with output method html
.
Question:
Is the URL that is output different (or even «damaged») than the one output in the first transformation?
Answer:
No, in both cases the same string was output — however in each case a different representation of the string was used.
Question:
Must I use the DOE ( disable-output-escaping="yes"
) attribute in order to output the wanted URL?
Answer:
No, as shown in the first transformation.
Question:
Is it recommended to use the DOE ( disable-output-escaping="yes"
) attribute in order to output the wanted URL?
Answer:
Нет, использование DOE является плохой практикой в XSLT и обычно сигнализирует о том, что программист плохо разбирается в модели обработки XSLT. Кроме того, DOE является лишь дополнительной функцией XSLT 1.0, и возможно, что ваш процессор XSLT не реализует DOE, или даже если это так, у вас могут возникнуть проблемы с выполнением того же преобразования с другим процессором XSLT.
Вопрос
Я перешел от другой проблемы к вопросу, за который получил награду. Моя проблема: я пытаюсь сгенерировать этот метод onclick:
<input type="submit" onClick="return confirm('are you sure?') amp;amp; confirm('seriously?');" />
что я могу сделать, так это: я могу поместить подтверждение в функцию … но
меня бесит, что я не могу сделать amp; внутри атрибута! Решение
этого вопроса, я думаю, и есть решение моей проблемы.
Ответ
На самом деле, вы можете указать amp;amp;
логическую операцию внутри выражения JavaScript внутри атрибута, представив ее как amp;amp;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;amp;amp; confirm('seriously?'));" />
</body>
</html>
JavaScript (script.js):
function confirm(message) {
alert(message);
return message === 'are you sure?';
}
Когда вы запустите это, вы сначала получите это предупреждение:
Затем, после нажатия на OK
кнопку, вы получите второе предупреждение:
И после нажатия OK
вы, наконец, получите предупреждение, которое приведет к результату amp;amp;
операции:
Вы можете поиграть с этим кодом, изменив значения аргументов, переданных confirm()
функции, и вы убедитесь, что полученные результаты соответствуют результатам использования amp;amp;
оператора.
Например, если вы измените <input>
элемент на этот:
<input type="submit"
onClick="alert(confirm('really sure?') amp;amp;amp;amp; confirm('seriously?'));" />
Сначала вы получите это предупреждение:
И когда вы нажмете OK
, вы сразу же получите окончательный результат amp;amp;
операции:
Второе предупреждение пропущено, потому что 1-й операнд amp;amp;
операции был false
, и JavaScript amp;amp;
сокращает, где находится 1-й операнд false
.
Подводя итог:
Оператор легко использовать amp;amp;
внутри атрибута в HTML-документе, сгенерированном XSLT, указав amp;amp;
операнд как amp;amp;amp;amp;
Комментарии:
1. Попробовал это, сеть транспортирует amp; amp; вместо amp;
2. Я перешел от другой проблемы к вопросу, за который получил награду. Моя проблема: я пытаюсь сгенерировать этот метод onclick:
<input type="submit" onClick="return confirm('are you sure?') amp;amp; confirm('seriously?');" />
что я могу сделать: я могу поместить подтверждение в функцию … но меня раздражает то, что я не могу сделатьamp;
внутри атрибута! Решение этого вопроса-это решение моей проблемы, я думаю.3. @PeterRader, просто используйте:
<input type="submit" onClick="return confirm('are you sure?') amp;amp;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;amp;amp; confirm('seriously?');" />
4. Javascript говорит мне, что amp не определен.
5. @PeterRader: Вообще говоря, когда вы внедряете фрагменты одного языка в другой, вы должны применять экранирование на каждом уровне. Типичным примером является строка в JavaScript в
onclick
атрибуте HTML в строке PHP. Кавычки внутри строки должны быть экранированы, чтобы сформировать правильную строку JavaScript. Весь фрагмент JavaScript должен быть экранирован (PHPhtmlspecialchars()
), чтобы быть встроенным в атрибут HTML. И HTML должен быть дополнительно экранирован, чтобы быть встроенным в строку PHP (обратные косые черты, кавычки,…). Дмитрий прав в том, что вы должны избежать amp; в атрибуте onclick.
Ответ №3:
Вы выражаете URI в HTML или XHTML? например <tag attr="http://foo.bar/?key=valueamp;amp;key2=value2amp;amp;..."/>
, если это так, « amp;amp;
» — правильный способ выразить амперсанд в значении атрибута, даже если он отличается от нужного вам буквального URI. Браузеры будут декодировать « amp;amp;
» и любую другую ссылку на сущность символов перед их загрузкой или передачей во Flash. Вставлять литерал, одинокий « amp;
» непосредственно в HTML или XHTML неверно.
Я также лично рекомендую больше узнать о XML, чтобы яснее думать о подобных вещах. Например, попробуйте чаще использовать W3C DOM (не только для тривиального Javascript); даже если вы не используете его изо дня в день, изучение DOM помогло мне правильно подумать о древовидной структуре XML и о том, как правильно кодировать атрибуты и элементы.
Ответ №4:
Используйте disable-output-escaping="yes"
в своем value-of
теге
Ответ №5:
Если вы создаете строку запроса как часть большего URL-адреса в атрибуте какого-либо другого тега (например, «встроить»), то вы действительно хотите, чтобы amp; был экранирован как amp;amp;. В то время как все браузеры поймут, что вы имеете в виду, и поступят Правильно, если вы передадите сгенерированный документ валидатору, он отметит не экранированное amp; в значении атрибута.
Ответ №6:
Если вы пытаетесь создать XML-файл в качестве выходного, вам потребуется создать amp;amp;
(так как amp;
сам по себе недопустимый XML). Если вы просто создаете строку, вам следует установить режим вывода таблицы стилей text
, включив следующее в качестве дочернего элемента xsl:stylesheet
<xsl:output method="text"/>
Это предотвратит ускользание из таблицы стилей и <xsl:value-of select="'amp;amp;'" />
должно привести amp;
к появлению .
Ответ №7:
Если ваше преобразование создает XML-документ, вы не должны отключать экранирование вывода. Вы хотите, чтобы символы разметки экранировались в выходных данных, чтобы не создавать искаженный XML. XML-объект, с помощью которого вы обрабатываете выходные данные (например, DOM), развернет текст для вас.
Если вы используете обработку строк вместо объекта XML для обработки выходных данных, у вас проблема. Но проблема не в вашем XSLT, а в решении использовать манипуляции со строками для обработки XML, что почти всегда плохо.
Если ваше преобразование создает HTML или текст (и вы установили тип вывода для <xsl:output>
элемента, верно?), это совсем другая история. Тогда это уместно использовать disable-output-escaping='yes'
на вашем <xsl:value-of>
элементе.
Но в любом случае вам нужно будет избежать символов разметки в текстовых узлах XSLT, если вы не завернули текст в раздел CDATA.
Ответ №8:
Отключение экранирования вывода приведет к job……as этот атрибут поддерживается только для текста, которым вы также можете управлять шаблоном, например:
<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=»да»..
Ответ №9:
Просто замените amp; на
<![CDATA[amp;]]>
в данных.
ПРИМЕР: XML-данные
<title>Empire <![CDATA[amp;]]> Burlesque</title>
Тег XSLT:
<xsl:value-of select="title" />
Выход:
Империя и бурлеск
Ответ №10:
Вы должны отметить, что вы можете использовать функцию отключения вывода в значении узла или строки/текста, например:
<xsl:value-of select="/node/here" disable-output-escaping="yes" />
или
<xsl:value-of select="'amp;amp;'" disable-output-escaping="yes" />
<xsl:text disable-output-escaping="yes">Texas Aamp;amp;M</xsl:text>
Обратите внимание на одинарные кавычки в xsl:значение.
Однако вы не можете использовать отключение экранирования вывода для атрибутов. Я знаю, что это полностью запутано, но так обстоит дело в XSLT 1.0. Поэтому следующее НЕ сработает:
<xsl:value-of select="/node/here/@ttribute" disable-output-escaping="yes" />
Потому что мелким шрифтом указана цитата:
Таким образом, ошибка заключается в отключении экранирования вывода для
<xsl:value-of />
<xsl:text />
элемента или, который используется для генерации строкового значения комментария, инструкции обработки или узла атрибута;
акцент мой.
Комментарии:
1. Это не совсем правильно. Вы можете использовать отключение экранирования вывода при передаче значения атрибута в исходном дереве, скажем, в текстовый узел. Ваш пример будет работать, если он не находится внутри элемента <xsl:атрибут> или шаблона значения атрибута.
2.
<xsl:value-of select="/node/here/@ttribute" disable-output-escaping="yes" />
это не пример того, что описано в цитате. Вы читаете атрибут, а не записываете его.
Ответ №11:
Использование disable-output-escaping
атрибута (логического значения), вероятно, является самым простым способом достижения этой цели. Обратите внимание , что вы можете использовать это не только на <xsl:value-of/>
, но и с <xsl:text>
, что может быть чище, в зависимости от вашего конкретного случая.
Вот соответствующая часть спецификации: http://www.w3.org/TR/xslt#disable-output-escaping
Ответ №12:
org.apache.xalan.xslt.Процесс, версия 2.7.2 выводит «Вот выполняемая, короткая и полная демонстрация того, как создать такой URL», упомянутая выше:
<?xml version="1.0" encoding="UTF-8"?>http://www.myUrl.com/?vA=aamp;amp;vX=xamp;amp;vY=yamp;amp;vZ=z11522
Объявление XML подавляется дополнительным omit-xml-declaration="yes"
, но, тем не менее, вывод method="text"
, ускользающий от амперсандов, не оправдан.
Комментарии:
1. Хорошо, я вижу, что у xalan есть дополнительный переключатель-ТЕКСТ для форматирования текста. В этом случае результат будет таким, как описано выше.
Ответ №13:
попробуйте: <xsl:значение выбора=»amp;amp;» отключить-вывод-экранирование=»да»/>
Извините, если форматирование испорчено.