Ответ 1
<xsl:template match="text">
<body>
<xsl:value-of select="." disable-output-escaping="yes" />
</body>
</xsl:template>
Обратите внимание, что на выходе не гарантируется корректность XML.
Мне нужно unescape XML-символы изнутри узлов XML с помощью только преобразований XSLT. У меня есть <text><>and other possible characters</text>
и нужно получить его как допустимый отформатированный HTML, когда я поместил его внутри тега body.
<xsl:template match="text">
<body>
<xsl:value-of select="." disable-output-escaping="yes" />
</body>
</xsl:template>
Обратите внимание, что на выходе не гарантируется корректность XML.
С xslt 2.0 я придумал этот. Обратите внимание, что на выходе не гарантируется правильность xml, простое неравенство может испортить ваш результат.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:character-map name="a">
<xsl:output-character character="<" string="<"/>
<xsl:output-character character=">" string=">"/>
</xsl:character-map>
<xsl:output use-character-maps="a"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Я не нашел ответа на этот вопрос. Поэтому я пришел к выводу, что это не способ сделать это. Я нашел обходной путь для этой проблемы, unescaping файл на стороне сервера.
Другое решение. Этот не использует постпроцессор xml, поэтому его можно использовать в качестве дополнительной обработки xslt. Также гарантируется создание допустимого xml. Это решение xslt 2.0, выходящее из текста в тегах "документации", протестированное с помощью саксона. Вы должны изменить переменную "allowedtags", чтобы определить свою собственную модель данных. Непосредственными детьми являются теги, а ниже - атрибуты. Чтение разрешенных тегов из xsd оставлено как упражнение для читателя (пожалуйста, поделитесь им со мной).
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://magwas.rulez.org/my"
>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:variable name="allowedtags">
<li/>
<ul/>
<br/>
<a><href/></a>
</xsl:variable>
<xsl:template match="@*|*|processing-instruction()|comment()" mode="unescape">
<xsl:copy>
<xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()" mode="unescape"/>
</xsl:copy>
</xsl:template>
<xsl:template match="documentation" mode="unescape">
<documentation>
<xsl:call-template name="doc">
<xsl:with-param name="str">
<xsl:value-of select="."/>
</xsl:with-param>
</xsl:call-template>
</documentation>
</xsl:template>
<xsl:template name="doc">
<xsl:param name="str"/>
<xsl:variable name="start" select="fn:substring-before($str,'<')"/>
<xsl:variable name="rest" select="fn:substring-after($str,'<')"/>
<xsl:variable name="fulltag" select="fn:substring-before($rest,'>')"/>
<xsl:variable name="tagparts" select="fn:tokenize($fulltag,'[ 
]')"/>
<xsl:variable name="tag" select="$tagparts[1]"/>
<xsl:variable name="aftertag" select="fn:substring-after($rest,'>')"/>
<xsl:variable name="intag" select="fn:substring-before($aftertag,fn:concat(fn:concat('</',$tag),'>'))"/>
<xsl:variable name="afterall" select="fn:substring-after($aftertag,fn:concat(fn:concat('</',$tag),'>'))"/>
<xsl:value-of select="$start"/>
<xsl:choose>
<xsl:when test="$tag">
<xsl:variable name="currtag" select="$allowedtags/*[$tag = local-name()]"/>
<xsl:if test="$currtag">
<xsl:element name="{$currtag/local-name()}">
<xsl:for-each select="$tagparts[position()>1]">
<xsl:variable name="anstring" select="fn:replace(.,'^([^ 
=]*)=.*$','$1')"/>
<xsl:variable name="antag" select="$currtag/*[$anstring = local-name()]"/>
<xsl:if test="$antag">
<xsl:attribute name="{$antag/local-name()}">
<xsl:value-of select="fn:replace(.,'^.*[^ "]*"([^"]*)".*','$1')"/>
</xsl:attribute>
</xsl:if>
</xsl:for-each>
<xsl:if test="$intag">
<xsl:call-template name="doc">
<xsl:with-param name="str">
<xsl:value-of select="$intag"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:element>
</xsl:if>
<xsl:if test="$afterall">
<xsl:call-template name="doc">
<xsl:with-param name="str">
<xsl:value-of select="$afterall"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>