XSLT 1.0(以及因此的 XPath 1.0)在其字符串操作功能方面有些限制。有substring-before
和函数允许您在特定模式的第一次substring-after
出现之前和之后提取给定字符串的子字符串,但是没有直接的方法在最后一次出现时分割字符串。您必须使用(尾)递归模板
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<xsl:template match="person/@name">
<xsl:call-template name="splitName"/>
</xsl:template>
<xsl:template name="splitName">
<!-- start with nothing in $first and all the words in $rest -->
<xsl:param name="first" select="''" />
<xsl:param name="rest" select="." />
<xsl:choose>
<!-- if rest contains more than one word -->
<xsl:when test="substring-after($rest, ' ')">
<xsl:call-template name="splitName">
<!-- move the first word of $rest to the end of $first and recurse.
For the very first word this will add a stray leading space
to $first, which we will clean up later. -->
<xsl:with-param name="first" select="concat($first, ' ',
substring-before($rest, ' '))" />
<xsl:with-param name="rest" select="substring-after($rest, ' ')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- $rest is now just the last word of the original name, and $first
contains all the others plus a leading space that we have to
remove -->
<xsl:attribute name="firstname">
<xsl:value-of select="substring($first, 2)" />
</xsl:attribute>
<xsl:attribute name="lastname">
<xsl:value-of select="$rest" />
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
例子:
$ cat names.xml
<people>
<person name="John Smith" />
<person name="Mary Ann Smith" />
</people>
$ xsltproc split-names.xsl names.xml
<?xml version="1.0"?>
<people>
<person firstname="John" lastname="Smith"/>
<person firstname="Mary Ann" lastname="Smith"/>
</people>
如果您不想要该<?xml...?>
行,请添加
<xsl:output method="xml" omit-xml-declaration="yes" />
到样式表的顶部,紧跟在开始<xsl:stylesheet>
标记之后。