Skip to content

Instantly share code, notes, and snippets.

@Flackus
Created March 1, 2011 16:10
Show Gist options
  • Save Flackus/849361 to your computer and use it in GitHub Desktop.
Save Flackus/849361 to your computer and use it in GitHub Desktop.
XML Reverser
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<!-- Паттерн на все элементы -->
<xsl:template match="*">
<!-- Реверсим локальную часть имени -->
<xsl:variable name="thisName">
<xsl:call-template name="checkNCName">
<xsl:with-param name="string" select="local-name()"/>
</xsl:call-template>
</xsl:variable>
<!-- Пересоздаем элемент с новым именем, прокидываем nsuri -->
<xsl:element name="{$thisName}" namespace="{namespace-uri()}">
<!-- Апплаимся на все атрибуты -->
<xsl:apply-templates select="@*"/>
<!-- Апплаимся на все ноды -->
<xsl:apply-templates>
<!-- Переворачиваем document order -->
<xsl:sort select="position()" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!-- Паттерн на все атрибуты -->
<xsl:template match="@*">
<!-- Реверсим локальную часть имени -->
<xsl:variable name="thisName">
<xsl:call-template name="checkNCName">
<xsl:with-param name="string" select="local-name()"/>
</xsl:call-template>
</xsl:variable>
<!-- Пересоздаем атрибут с новым именем, прокидываем nsuri -->
<xsl:attribute name="{$thisName}" namespace="{namespace-uri()}">
<!-- Реверсим значение атрибута -->
<xsl:call-template name="string-reverser"/>
</xsl:attribute>
</xsl:template>
<!-- Священные коровы -->
<xsl:template match="@xml:*">
<xsl:copy/>
</xsl:template>
<!-- Паттерн на все текстовые ноды -->
<xsl:template match="text()">
<!-- Реверсим строковое значение -->
<xsl:call-template name="string-reverser"/>
</xsl:template>
<!-- Копируем комменты и инструкции обработки -->
<xsl:template match="comment() | processing-instruction()">
<xsl:copy/>
</xsl:template>
<!-- Храним символы, с которых можно начать NCName -->
<!-- Cюда можно положить НЕ любой NCNameChar, а "( Letter | «_» )" -->
<xsl:variable name="genName" select="
concat(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz',
'_'
)
"/>
<!-- Проверяем создаваемое имя -->
<xsl:template name="checkNCName">
<xsl:param name="string" select="."/>
<!-- Отрезаем последний символ строки -->
<xsl:variable name="curLastSymbol" select="
substring($string, string-length($string))
"/>
<xsl:choose>
<!-- Если последний символ это символ не из $genName -->
<xsl:when test="
string(
translate(
$curLastSymbol, $genName, ''
)
)
">
<!-- Рекурсивно запускаем текущий шаблон -->
<xsl:call-template name="checkNCName">
<!-- Передаем строку _без_ последнего символа -->
<xsl:with-param name="string" select="
substring($string, 0, string-length($string))
"/>
</xsl:call-template>
</xsl:when>
<!-- Если все ок, реверсим локальную часть имени -->
<xsl:otherwise>
<xsl:call-template name="string-reverser">
<xsl:with-param name="string" select="$string"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Реверсер строки -->
<xsl:template name="string-reverser">
<xsl:param name="string" select="."/>
<xsl:param name="stringReversed"/>
<xsl:choose>
<!-- Пока остается оригинальная строка -->
<xsl:when test="$string">
<xsl:call-template name="string-reverser">
<!-- Передаем без первого символа -->
<xsl:with-param name="string" select="substring($string, 2)"/>
<!-- Отрезаем первый символ и кладем в новую строку -->
<xsl:with-param name="stringReversed" select="
concat(substring($string, 1, 1), $stringReversed)
"/>
</xsl:call-template>
</xsl:when>
<!-- Иначе закончили переворачивать -->
<xsl:otherwise>
<xsl:value-of select="$stringReversed"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment