XSLT - 仅首字母大写,但如何处理像 McDermott 这样的名字
Posted
技术标签:
【中文标题】XSLT - 仅首字母大写,但如何处理像 McDermott 这样的名字【英文标题】:XSLT - Capitalize first letter only but how to handle names like McDermott 【发布时间】:2021-12-27 19:01:42 【问题描述】:我使用以下代码仅将首字母大写,但不想将 McDermott 转换为 Mcdermott。 在代码中如何处理这样的异常?
<xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/>
<xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/>
<xsl:variable name="numeric" select="0123456789"/>
<xsl:variable name="alpha-numeric" select="concat($lowers,$uppers,$numeric)"/>
<xsl:template name="capitalize">
<xsl:param name="val"/>
<xsl:param name="alphanumeric-seen" select="false()"/>
<xsl:variable name="head" select="substring($val, 1, 1)"/>
<xsl:if test="$head">
<xsl:variable name="is-alpha-numeric" select="not(translate($head, $alpha-numeric, ''))"/>
<xsl:variable name="tail" select="substring($val, 2)"/>
<xsl:choose>
<xsl:when test="$is-alpha-numeric">
<xsl:choose>
<xsl:when test="$alphanumeric-seen">
<xsl:value-of select="$head"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate($head, $lowers, $uppers)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="capitalize">
<xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/>
<xsl:with-param name="alphanumeric-seen" select="true()"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$head"/>
<xsl:call-template name="capitalize">
<xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/>
<xsl:with-param name="alphanumeric-seen" select="false()"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
【问题讨论】:
您可以对以“Mc”或“Mac”开头的名称进行例外处理,但有些人将他们的名字写成“MacDonald”,而其他人则写成“Macdonald” - 所以如果你没有确切的原件名字,无论你做什么,你都可能得罪某人。另请注意,还有其他例外情况,例如奥黑尔或达达尼昂。 嗨,帕蒂。这是一个“规范化”问题,一般适用于任何类型的输入/输出,而不是专门的 XSLT 问题。 【参考方案1】:为了给你一个方向,请使用这个 xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<xsl:output indent="yes"/>
<xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/>
<xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/>
<xsl:variable name="numeric" select="0123456789"/>
<xsl:template match="/names">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="name">
<xsl:variable name="orgLength" select="string-length(.)"/>
<xsl:variable name="allLowersSkipt" select="translate(.,$lowers,'')"/>
<xsl:variable name="allUppersSkipt" select="translate(.,$uppers,'')"/>
<xsl:variable name="allNumericSkiptLength" select="string-length(translate(.,$numeric,''))"/>
<xsl:variable name="allUppersSkiptLength" select="string-length($allUppersSkipt)"/>
<xsl:variable name="allLowersSkiptLength" select="string-length($allLowersSkipt)"/>
<xsl:variable name="firstCapital" select="concat(translate(substring(.,1,1),$lowers,$uppers),translate(substring(.,2),$uppers,$lowers))"/>
<xsl:copy>
<xsl:comment>Org: <xsl:value-of select="."/></xsl:comment>
<xsl:choose>
<xsl:when test="$allNumericSkiptLength!=$orgLength">
<xsl:comment>Contains Number</xsl:comment>
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="$firstCapital=.">
<xsl:comment>Already Correct</xsl:comment>
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="$allUppersSkiptLength=0">
<xsl:comment>All Uppers</xsl:comment>
<xsl:value-of select="$firstCapital"/>
</xsl:when>
<xsl:when test="$allLowersSkiptLength=0">
<xsl:comment>All Lowers</xsl:comment>
<xsl:value-of select="$firstCapital"/>
</xsl:when>
<xsl:otherwise>
<xsl:comment>Contains a combination of Lowers and Uppers</xsl:comment>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在这个 xml 上使用时:
<?xml version="1.0" encoding="UTF-8"?>
<names>
<name>MacDonaldMet1</name>
<name>McDermott</name>
<name>ALLCAPITAL</name>
<name>alllower</name>
<name>Firstcapital</name>
<name>MacDonald</name>
</names>
给出这个结果:
<?xml version="1.0" encoding="UTF-8"?>
<names>
<name><!--Org: MacDonaldMet1--><!--Contains Number-->MacDonaldMet1</name>
<name><!--Org: McDermott--><!--Contains a combination of Lowers and Uppers-->McDermott</name>
<name><!--Org: ALLCAPITAL--><!--All Uppers-->Allcapital</name>
<name><!--Org: alllower--><!--All Lowers-->Alllower</name>
<name><!--Org: Firstcapital--><!--Already Correct-->Firstcapital</name>
<name><!--Org: MacDonald--><!--Contains a combination of Lowers and Uppers-->MacDonald</name>
</names>
【讨论】:
以上是关于XSLT - 仅首字母大写,但如何处理像 McDermott 这样的名字的主要内容,如果未能解决你的问题,请参考以下文章
使用 XSLT 1.0 进行多项更改(大写元素首字母、顺序元素、聚合/组元素)