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 这样的名字的主要内容,如果未能解决你的问题,请参考以下文章

Latex中标题全变为大写了,如何得到仅首字母大写?

字符串 - 大写

使用 XSLT 1.0 进行多项更改(大写元素首字母、顺序元素、聚合/组元素)

将人名大写(占 ' 和 - )

LeetCode 917. 仅仅反转字母 / 1706. 球会落何处 / 537. 复数乘法

如何使用 XSLT 将字符串转换为大写或小写?