Один из способов сделать это - использовать рекурсивный шаблон, который рекурсивно проверяет каждую букву атрибута type строки.Итак, чтобы создать первый элемент, вы должны сделать следующее (где $ type - переменная, содержащая значение атрибута):
<xsl:element name="{substring($type, 1, 1)}">
Затем вы будете рекурсивно вызывать именованный шаблон с оставшейся частью значения атрибута
<xsl:call-template name="Line">
<xsl:with-param name="type" select="substring($type, 2)"/>
</xsl:call-template>
Итак, учитывая следующее XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Line" name="Line">
<xsl:param name="type" select="@type"/>
<xsl:choose>
<xsl:when test="not($type)">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{substring($type, 1, 1)}">
<xsl:call-template name="Line">
<xsl:with-param name="type" select="substring($type, 2)"/>
</xsl:call-template>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Применительно к следующему XML
<Lines>
<Line type="B">stackoverflow</Line>
<Line type="U">stackoverflow</Line>
<Line type="BU">stackoverflow</Line>
<Line>No format</Line>
</Lines>
Будет выводить следующее
<Lines>
<B>stackoverflow</B>
<U>stackoverflow</U>
<B><U>stackoverflow</U></B>
No format
</Lines>
Обратите внимание, что для остановки вывода элемента Lines в этом случае просто добавьте следующий шаблон в XSLT:
<xsl:template match="Lines">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>