Этот вопрос очень актуален для этого XSLT преобразует узел <image> в тег <img> при выводе в DOM
Рассмотрим этот фрагмент кода:
<script type = "application/xml" id = "data">
<xsl:copy-of select = "/*" />
</script>
Это выведет содержимое XML-документа на html-страницу. Тогда очень легко анализировать данные из XML с помощью объекта DOMParser() в javascript, что делает их легко доступными на веб-странице без необходимости использования XSLT для создания веб-страницы.
Перемещение <xsl:copy-of select"/*" /> между тегами сценария требовалось, чтобы преобразователь XSLT не преобразовывал узел в файле XML в теги HTML.
Это работало отлично, пока я не узнал, что то же самое происходит и с узлом. Проще говоря: если у XML есть узел, вывод будет испорчен и не поддается анализу, например:
Как предотвратить такое поведение? Как запретить движку браузера делать тег самозакрывающимся?
new DOMParser().parseFromString()
/\ Не будет работать с самозакрывающимися узлами. (ПОЯСНЕНИЕ: очевидно, что DOMParser БУДЕТ работать с самозакрывающимися узлами, просто в этом случае он не был самозакрывающимся, т.е. не имел косой черты)
Итак, вот файлы, которые необходимы для воспроизведения этого:
test.xslt
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
<xsl:output method = "html" indent = "no" version = "5.0" />
<xsl:template match = "/">
<xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text>
<xsl:apply-templates select = "root" />
</xsl:template>
<xsl:template match = "root">
<html>
<head>
<script type='application/xml'>
<xsl:copy-of select = "/*" />
</script>
</head>
<body>
<div>qwe</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
test.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<?xml-stylesheet type = "text/xsl" href = "test.xslt"?>
<root>
<object>
<text>text</text>
<param name = "name"></param>
</object>
</root>
Откройте test.xml с помощью Edge в режиме совместимости с Internet Explorer 11. В "голове" должен быть скрипт с искаженным xml.
В Windows 10 вы можете открыть Инструменты разработчика, выполнив «Выполнить (Win+R)» -> «%systemroot%\system32\f12\IEChooser.exe» после открытия XML-файла.
Возможная чистая сериализация XML в формате XSLT 1 — lenzconsulting.com/xml-to-string.
Я просто открываю XML-файл с помощью Edge в режиме совместимости с IE11. *.xslt файл со всеми шаблонами находится в одной папке
Но вы используете как преобразование XSLT на основе xml-stylesheet
pi в некоторых XML, так и более позднее преобразование XSLT, запускаемое Javascript? Мне не понятна вся последовательность обработки, в каком моменте вы используете элемент script
с xsl:copy-of
внутри и где вам потом нужно обрабатывать содержимое элемента скрипта. Но в XSLT 1, если вам нужно сериализовать узел XML, используйте библиотеку, которая может это сделать.
Не важно. Я обновил вопрос, включив в него содержимое двух файлов — test.xml и test.xslt. Я просто открываю test.xml с помощью Edge в режиме IE11 и все. У меня на компьютере установлен MSXML4, если это что-то меняет (я установил его, потому что директива <xsl:include> без него не работала). Полагаю, мне все-таки придется использовать библиотеки.
Будем надеяться, что кто-нибудь сможет вам помочь. Мне кажется, что Edge в Windows 11 полностью основан на Chromium, и у меня даже нет возможности включить режим совместимости с IE. Запуск XSLT на основе файла с таблицей стилей xml не поддерживается в Edge или Chromium.
Что касается моего предложения по сериализации с использованием библиотеки, вот как это будет выглядеть (при реальном использовании не импортируйте через HTTP(S), используйте локальную копию xsl:import
):
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
version = "1.0">
<xsl:import href = "https://lenzconsulting.com/xml-to-string/xml-to-string.xsl"/>
<xsl:output method = "html" indent = "no" version = "5.0" doctype-system = "about:legacy-doctype" />
<xsl:template match = "/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match = "root">
<html>
<head>
<script type='application/xml'>
<xsl:apply-templates select = "." mode = "xml-to-string"/>
</script>
</head>
<body>
<div>qwe</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Это должно дать вам элемент script
, который в качестве текстового/CDATA-содержимого имеет сериализацию элемента root
входного документа.
Что касается способа сериализации пустых элементов, в XML это не имеет значения, но библиотека позволяет вам установить <xsl:param name = "use-empty-syntax" select = "false()"/>
, чтобы получить, например. <param name = "name"></param>
.
Ты снова спас мою шкуру. Эта библиотека полностью работает и делает то, что нужно. Единственная причуда, которую я обнаружил, заключается в том, что тег <param> закрывается, если он пуст, что делает его самозакрывающимся тегом. Но это нормально, поскольку DOMParser ДЕЙСТВИТЕЛЬНО работает с самозакрывающимися узлами. Итак, результат: xml <object> <param name = "name" /> </object>
По какой-то причине он не делает этого для других пустых узлов.
Единственное, чего я боюсь, это потерять эту библиотеку, если сайт выйдет из строя :) (я скачал ее для локального использования, но все же - что, если кто-то еще столкнется с той же проблемой, но решение недоступно)
@GlennCarver, библиотека позволяет вам установить параметр use-empty-syntax
на false()
, чтобы пустые элементы были сериализованы с помощью начального и конечного тега. Что касается закрытия сайта, будем надеяться, что Эван продолжит его работу. Конечно, с 2017 года мы живем в мире XSLT 3, где есть встроенная функция XPath 3.1 fn:serialize
, поддерживаемая на широком спектре платформ и в широком спектре сред такими реализациями, как Saxon Java, SaxonC, SaxonJS, Saxon. NET и различные инструменты Altova XML (XML Spy, Raptor), поэтому существуют современные компактные альтернативы. Однако не уверен, что есть способ для IE.
Какова среда для запуска XSLT/XPath, которая выполняет
<xsl:copy-of select = "/*" />
? В идеале содержимое элементаscript
должно быть сериализовано в формате XML. Сложно в XSLT 1, но есть библиотеки XSLT 1.0 для сериализации и/или с помощью MSXML в IE, возможно, можно будет вызвать J(ava)Script для сериализации узла.