Не удается заставить xslt выводить (

#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 должен быть экранирован (PHP htmlspecialchars() ), чтобы быть встроенным в атрибут 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 /> элемента или, который используется для генерации строкового значения комментария, инструкции обработки или узла атрибута;

акцент мой.

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

Комментарии:

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;» отключить-вывод-экранирование=»да»/>

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