Это преобразование является более общим и расширяемым :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:variable name="vAttributesResult">
<xsl:call-template name="processAttributes"/>
</xsl:variable>
<xsl:value-of select=
"concat(substring-before($vAttributesResult, ' '),
.,
substring-after($vAttributesResult, ' ')
)
"/>
</xsl:template>
<xsl:template name="processAttributes">
<xsl:param name="pattrList" select="@*"/>
<xsl:param name="pResult" select="' '"/>
<xsl:choose>
<xsl:when test="not($pattrList)">
<xsl:value-of select="$pResult"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vthisResult">
<xsl:apply-templates select="$pattrList[1]">
<xsl:with-param name="pResult" select="$pResult"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name="processAttributes">
<xsl:with-param name="pattrList" select="$pattrList[position()>1]"/>
<xsl:with-param name="pResult" select="$vthisResult"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@font-weight[.='bold']">
<xsl:param name="pResult"/>
<xsl:value-of select="concat('\b', $pResult, '\b0')"/>
</xsl:template>
<xsl:template match="@font-style[.='italic']">
<xsl:param name="pResult"/>
<xsl:value-of select="concat('\i', $pResult, '\i0')"/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML (исправлено, чтобы быть правильно сформированным):
<fo:block font-weight="bold" font-style="italic"
xmlns:fo="some:fo">Some Text Here</fo:block>
желаемый результат получен :
\i\bSome Text Here\b0\i0
Примечание :
Выможно легко добавить обработку для стольких новых комбинаций атрибутов / значений, сколько необходимо - просто добавьте новый шаблон для нового атрибута.
Если порядок важен, используйте эти шаблоны для обработки атрибутов:
-
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:text>{</xsl:text>
<xsl:apply-templates select="@*">
<xsl:with-param name="pSuff" select="''"/>
<xsl:sort select="position()"/>
</xsl:apply-templates>
<xsl:apply-templates select="node()" />
<xsl:apply-templates select="@*">
<xsl:with-param name="pSuff" select="'0'"/>
<xsl:sort select="position()" order="descending"/>
</xsl:apply-templates>
<xsl:text>\par}</xsl:text>
</xsl:template>
<xsl:template match="@font-weight['bold']">
<xsl:param name="pSuff"/>
<xsl:value-of select="concat('\b',$pSuff)"/>
</xsl:template>
<xsl:template match="@font-style['italic']">
<xsl:param name="pSuff"/>
<xsl:value-of select="concat('\i',$pSuff)"/>
</xsl:template>
</xsl:stylesheet>
Это преобразование заимствует идею ответа от @ Flynn1169 и значительно упрощает ее (только 3 шаблона вместо t и никаких режимов) и, что наиболее важно, представляет результаты в соответствии с лексическим порядком атрибутов.
В этом случае результат соответствует лексическому порядку атрибутов, а не их отсортированных имен !:
Если у нас есть этот XML-документ :
<fo:block font-style="italic" font-weight="bold"
xmlns:fo="some:fo">Some Text Here</fo:block>
, результат теперь будет:
{\i\bSome Text Here\b0\i0\par}
Примечание : Хотя в модели данных XPath нет ничего как «порядок атрибутов», все процессоры XSLT, с которыми я работаю (более 9) в режиме push-стиля, выдают результаты обработки атрибутов в соответствии с их лексическойзаказ.