Вот простое преобразование - для начала :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pIndents" select="' '"/>
<xsl:template match="*[*]">
<xsl:param name="pcurrentIndents" select="''"/>
<xsl:value-of select="concat($pcurrentIndents, name(), ':')"/>
<xsl:value-of select="concat('
',$pcurrentIndents, '{')"/>
<xsl:apply-templates>
<xsl:with-param name="pcurrentIndents" select=
"concat($pcurrentIndents, $pIndents)"/>
</xsl:apply-templates>
<xsl:value-of select="concat('
',$pcurrentIndents, '}')"/>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:param name="pcurrentIndents" select="''"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="concat($pcurrentIndents, name(), ':')"/>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
когда это преобразование применяется к предоставленному документу XML :
<person>
<name>
<name-first>foo</name-first>
<name-last>bar</name-last>
</name>
<age>20</age>
<city>nowhere</city>
</person>
желаемый, правильный результат получается :
person:
{ name:
{
name-first:foo
name-last:bar
}
age:20
city:nowhere
}
Объяснение
Существует два шаблона, соответствующих элементам.
Шаблон, соответствующий *[*]
, соответствует элементам, у которых есть дочерние элементы. Он генерирует имя соответствующего элемента, используя функцию name()
, затем символ :
, затем символ NL, текущий отступ (количество пробелов) и, наконец, символ {
. Затем шаблоны применяются к дочерним узлам текущего сопоставляемого элемента с параметром $pcurrentIndents
, передающим текущее отступ, увеличенный с заранее заданным шагом пробелов (как указано в глобальном параметре $pIndents
Наконец, на новой строке и с использованием текущий отступ, закрывающая фигурная скобка является положительной.
Шаблон, соответствующий *[not(*)]
(элементы, у которых нет дочерних элементов), похож, но проще. Выводит имя соответствующего элемента с текущим отступом и символ :
. Применение шаблонов здесь вызывает встроенные шаблоны XSLT для неэлементных узлов - в этом случае выбирается встроенный шаблон, соответствующий текстовому узлу, и он просто копирует текстовый узел в выходные данные.