Следующий шаблон будет выдавать все числовые цифры строки вплоть до первой нечисловой (без необходимости знать, сколько цифр может быть в числе):
<xsl:template match="@num">
<xsl:variable name="nonNumbers" select="translate(., '0123456789', '')"/>
<xsl:attribute name="{name()}">
<xsl:choose>
<xsl:when test="$nonNumbers">
<xsl:value-of select="substring-before(.,
substring($nonNumbers, 1, 1))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
(Спасибо @Alejandroдля ключевой идеи, используя substring (), чтобы получить первое не-число, и затем передать его в substring-before ().) Здесь это в контексте преобразования идентичности:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@num">
<xsl:variable name="nonNumbers" select="translate(., '0123456789', '')"/>
<xsl:attribute name="{name()}">
<xsl:choose>
<xsl:when test="$nonNumbers">
<xsl:value-of select="substring-before(., substring($nonNumbers, 1, 1))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
<!-- Identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Когдазапустите следующий ввод:
<?xml version="1.0" encoding="UTF-8"?>
<values>
<value num="12"/>
<value num="5 ASDF"/>
<value num="34SDF56"/>
</values>
он выдаст запрошенный вывод:
<?xml version="1.0" encoding="utf-8"?>
<values>
<value num="12"/>
<value num="5"/>
<value num="34"/>
</values>
Другой способ сделать шаблон @num
заключается в следующем, возможно, более элегантном, но труднее для чтенияIMO:
<xsl:template match="@num[translate(., '0123456789', '') = '']">
<!-- alternatively, match="@num[number(.) > 0]" -->
<xsl:copy />
</xsl:template>
<xsl:template match="@num">
<xsl:attribute name="{name()}">
<xsl:value-of select="substring-before(., substring(
translate(., '0123456789', ''), 1, 1))" />
</xsl:attribute>
</xsl:template>
Примечания:
- Первый из двух вышеприведенных шаблонов @num имеет приоритет над вторым, поскольку первый более конкретен,имеющий предикат.Таким образом, первый шаблон используется для обработки @ num, которые ему соответствуют, а второй шаблон обрабатывает все остальные @ num.
- Первый шаблон соответствует @ num, значение которого состоит из всех цифр, и просто копирует атрибут.Если бы мы не сделали это исключение, второй шаблон вывел бы пустые строковые значения для таких @ num.