Ответ на этот вопрос более сложный, чем вы могли подумать. Должно произойти правильное «двойное экранирование» значений атрибутов и текстовых узлов.
Этот шаблон XSLT 1.0 выполняет правильную (хотя и не полную) печать узла XML, включая (попытку сделать) правильную красивую печать с настраиваемым отступом:
<code><xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="html" encoding="utf-8" />
<!-- defaults and configurable parameters -->
<xsl:param name="NL" select="'
'" /><!-- newline sequence -->
<xsl:param name="INDENTSEQ" select="'	'" /><!-- indent sequence -->
<xsl:variable name="LT" select="'<'" />
<xsl:variable name="GT" select="'>'" />
<xsl:template match="transform-me">
<html>
<body>
<!-- this XML-escapes an entire sub-structure -->
<pre><xsl:apply-templates select="*" mode="XmlEscape" />
</ XSL: шаблон>
<! - здесь будут обрабатываться узлы элементов, в т.ч. правильный отступ ->
</ XSL: если>
<! - рендерить дочерние узлы ->
</ XSL: Наносить-шаблоны>
</ XSL: если>
</ XSL: когда>
</ XSL: в противном случае>
</ XSL: выберите>
</ XSL: шаблон>
<! - комментарии будут обрабатываться здесь ->
</ XSL: шаблон>
<! - текстовые узлы будут напечатаны XML-экранированными ->
</ XSL: вызов-шаблон>
</ XSL: если>
</ XSL: шаблон>
<! - атрибуты становятся строкой: '{name ()} = "{escaped-value ()}"' ->
</ XSL: вызов-шаблон>
</ XSL: шаблон>
<! - шаблон для XML-экранирования строки ->
<! - символы &, <и> никогда не допускаются ->
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: вызов-шаблон>
</ XSL: переменная>
<! - chars ", TAB, CR и LF никогда не допускаются в атрибутах ->
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: вызов-шаблон>
</ XSL: переменная>
</ XSL: когда>
</ XSL: в противном случае>
</ XSL: выберите>
</ XSL: шаблон>
<! - шаблон замены общей строки ->
</ XSL: вызов-шаблон>
</ XSL: если>
</ XSL: когда>
</ XSL: в противном случае>
</ XSL: выберите>
</ XSL: шаблон>
</ XSL: таблицы стилей>
Применительно к этому тесту XML:
<transform-me>
<node id="1">
<!-- a comment -->
<stuff type="fl"' 	oatsam">
<details>Various bits & pieces</details>
<details>
</details>
<details attr="value">
<childnode>text and <escaped-text /></childnode>
</details>
</stuff>
</node>
</transform-me>
Производится следующий вывод (исходный код):
<code><html>
<body>
<pre><node id="1">
<!-- a comment -->
<stuff type="fl&quot;'&#xD;&#x9;oatsam">
<details>Various bits &amp; pieces</details>
<details />
<details attr="value">
<childnode>text and &lt;escaped-text /&lt;</childnode>
</details>
</stuff>
</node>
и при просмотре в браузере вы видите:
<node id="1">
<!-- a comment -->
<stuff type="fl"'
	oatsam">
<details>Various bits & pieces</details>
<details />
<details attr="value">
<childnode>text and <escaped-text /<</childnode>
</details>
</stuff>
</node>
Обратите внимание, что под "не завершенным" я подразумеваю, что такие вещи, как пространства имен и инструкции обработки, например, в настоящее время не обрабатываются. Но для них легко сделать шаблон.