Как вы можете работать со встроенными тегами XML в XSLT?
Я использую XSLT для преобразования XML в HTML. Мне трудно понять, как обращаться со встроенными XML-узлами для форматирования. Например, допустим, что у меня есть элемент XML:
<favoriteMovie>the <i>Star Wars</i> saga</favoriteMovie>
Однако во время XLST тег <i>
игнорируется, поэтому "Звездные войны" не выделяются курсивом в выход HTML. Есть ли относительно простой способ исправить это?
test.xml:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="test.html.xsl"?>
<favoriteMovies>
<favoriteMovie>the <i>Star Wars</i> saga</favoriteMovie>
</favoriteMovies>
test.html.xsl:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="/">
<html>
<head />
<body>
<ul>
<xsl:for-each select="favoriteMovies/favoriteMovie">
<li><xsl:value-of select="." /></li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Ответы
Ответ 1
Однако во время XLST тег <i>
получает игнорируется, поэтому "Звездные войны" не курсивом в выводе HTML. Является существует относительно простой способ исправить это?
Ваша проблема здесь:
<ul>
<xsl:for-each select="favoriteMovies/favoriteMovie">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
Команда <xsl:value-of>
используется для создания текста node. При этом он копирует на выход строковое значение выражения XPath, указанного в атрибуте select
этой инструкции XSLT. Строковое значение элемента представляет собой конкатенацию всех его потомков text-node.
Таким образом, вы получаете сообщение о выходе.
Решение
Используйте команду <xsl:copy-of>
, которая копирует все узлы, указанные в атрибуте select
<ul>
<xsl:for-each select="favoriteMovies/favoriteMovie">
<li><xsl:copy-of select="node()"/></li>
</xsl:for-each>
</ul>
Другое решение, более связанное с принципами XSLT, позволяет избежать использования <xsl:for-each>
вообще:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<html>
<head />
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="/*">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="favoriteMovie">
<li><xsl:copy-of select="node()"/></li>
</xsl:template>
</xsl:stylesheet>
Если любое из двух решений, определенных выше, применяется к предоставленному XML-документу:
<favoriteMovies>
<favoriteMovie>the
<i>Star Wars</i> saga
</favoriteMovie>
</favoriteMovies>
требуется, правильный результат получается:
<html>
<head/>
<body>
<ul>
<li>the
<i>Star Wars</i> saga
</li>
</ul>
</body>
</html>
Ответ 2
Вы должны использовать xsl: copy для копирования я node.
http://msdn.microsoft.com/en-us/library/ms256128.aspx
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="/">
<html>
<head />
<body>
<xsl:apply-templates></xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="favoriteMovies">
<ul>
<xsl:apply-templates></xsl:apply-templates>
</ul>
</xsl:template>
<xsl:template match="favoriteMovie">
<li>
<xsl:apply-templates></xsl:apply-templates>
</li>
</xsl:template>
<xsl:template match="i">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Ответ 3
Вам следует использовать атрибут "disable-output-escaping". Общий формат элемента:
<xsl:value-of select="expression" disable-output-escaping="yes|no" />
'disable-output-escaping' не является обязательным. "yes" указывает, что специальные символы (например, "<" ) должны выводиться как есть. "no" указывает, что специальные символы (например, "<" ) должны выводиться как "<" . По умолчанию "нет".
Поэтому просто измените свой код на:
<xsl:template match="favoriteMovie">
<xsl:copy-of select="node()" disable-output-escaping="yes"/>
</xsl:template>
Ответ 4
Следует отметить две вещи.
Во-первых. Убедитесь, что теги экранированы в CDATA
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="test.html.xsl"?>
<favoriteMovies>
<favoriteMovie><![CDATA[the <i>Star Wars</i> saga]]></favoriteMovie>
</favoriteMovies>
Во-вторых. Отключить выход:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="/">
<html>
<head />
<body>
<ul>
<xsl:for-each select="favoriteMovies/favoriteMovie">
<li><xsl:value-of select="." disable-output-escaping="yes" /></li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
EDIT: управлял им с помощью редактора, теперь код отображается как он должен
EDIT2: включены изменения в ваш код
EDIT3: К кому это может относиться, сама область рассматриваемой проблемы связана с структурированием информации о фильмах, а не с данными html. HTML существует только для разметки, представьте себе, что, например, тег заголовка html внутри favoriteMovie, в то время как название тега с названием тега может быть допустимым тегом в базе данных фильмов. Этот заголовок ЧЕТКОГО следует интерпретировать по-разному. Это оправдывает использование CDATA, а затем отключает вывод при обработке.