XSLT — Заглавная только первая буква, но как обращаться с такими именами, как Макдермотт

#xml #xslt #xslt-1.0

Вопрос:

Я использовал приведенный ниже код только для заглавной буквы, но не хочу преобразовывать McDermott в Mcdermott. Как можно обрабатывать подобные исключения в коде?

 lt;xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/gt;  lt;xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/gt;  lt;xsl:variable name="numeric" select="0123456789"/gt;  lt;xsl:variable name="alpha-numeric" select="concat($lowers,$uppers,$numeric)"/gt;  lt;xsl:template name="capitalize"gt;  lt;xsl:param name="val"/gt;  lt;xsl:param name="alphanumeric-seen" select="false()"/gt;  lt;xsl:variable name="head" select="substring($val, 1, 1)"/gt;  lt;xsl:if test="$head"gt;  lt;xsl:variable name="is-alpha-numeric" select="not(translate($head, $alpha-numeric, ''))"/gt;  lt;xsl:variable name="tail" select="substring($val, 2)"/gt;  lt;xsl:choosegt;  lt;xsl:when test="$is-alpha-numeric"gt;  lt;xsl:choosegt;  lt;xsl:when test="$alphanumeric-seen"gt;  lt;xsl:value-of select="$head"/gt;  lt;/xsl:whengt;  lt;xsl:otherwisegt;  lt;xsl:value-of select="translate($head, $lowers, $uppers)"/gt;  lt;/xsl:otherwisegt;  lt;/xsl:choosegt;  lt;xsl:call-template name="capitalize"gt;  lt;xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/gt;  lt;xsl:with-param name="alphanumeric-seen" select="true()"/gt;  lt;/xsl:call-templategt;  lt;/xsl:whengt;  lt;xsl:otherwisegt;  lt;xsl:value-of select="$head"/gt;  lt;xsl:call-template name="capitalize"gt;  lt;xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/gt;  lt;xsl:with-param name="alphanumeric-seen" select="false()"/gt;  lt;/xsl:call-templategt;  lt;/xsl:otherwisegt;  lt;/xsl:choosegt;  lt;/xsl:ifgt;  lt;/xsl:templategt;  

Комментарии:

1. Вы можете сделать исключения для имен, которые начинаются с «Mc» или «Mac», но некоторые люди пишут свое имя как «Макдональд», а другие как «Макдональд», поэтому, если у вас нет точных оригинальных имен, вы, скорее всего, обидите кого — то, что бы вы ни делали. Обратите также внимание, что есть и другие исключения, например, О’Хара или д’Артаньян.

2. Привет, Пэтти. Это проблема «нормализации» для любого вида ввода/вывода в целом, а не проблема XSLT в частности.

Ответ №1:

Чтобы дать вам направление, используйте этот xslt:

 lt;?xml version="1.0" encoding="UTF-8"?gt; lt;xsl:stylesheet   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   version="1.0"  gt;  lt;xsl:output indent="yes"/gt;  lt;xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/gt;  lt;xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/gt;  lt;xsl:variable name="numeric" select="0123456789"/gt;    lt;xsl:template match="/names"gt;  lt;xsl:copygt;  lt;xsl:apply-templates/gt;  lt;/xsl:copygt;  lt;/xsl:templategt;    lt;xsl:template match="name"gt;  lt;xsl:variable name="orgLength" select="string-length(.)"/gt;  lt;xsl:variable name="allLowersSkipt" select="translate(.,$lowers,'')"/gt;  lt;xsl:variable name="allUppersSkipt" select="translate(.,$uppers,'')"/gt;  lt;xsl:variable name="allNumericSkiptLength" select="string-length(translate(.,$numeric,''))"/gt;  lt;xsl:variable name="allUppersSkiptLength" select="string-length($allUppersSkipt)"/gt;  lt;xsl:variable name="allLowersSkiptLength" select="string-length($allLowersSkipt)"/gt;  lt;xsl:variable name="firstCapital" select="concat(translate(substring(.,1,1),$lowers,$uppers),translate(substring(.,2),$uppers,$lowers))"/gt;   lt;xsl:copygt;  lt;xsl:commentgt;Org: lt;xsl:value-of select="."/gt;lt;/xsl:commentgt;  lt;xsl:choosegt;  lt;xsl:when test="$allNumericSkiptLength!=$orgLength"gt;  lt;xsl:commentgt;Contains Numberlt;/xsl:commentgt;  lt;xsl:value-of select="."/gt;  lt;/xsl:whengt;  lt;xsl:when test="$firstCapital=."gt;  lt;xsl:commentgt;Already Correctlt;/xsl:commentgt;  lt;xsl:value-of select="."/gt;  lt;/xsl:whengt;  lt;xsl:when test="$allUppersSkiptLength=0"gt;  lt;xsl:commentgt;All Upperslt;/xsl:commentgt;  lt;xsl:value-of select="$firstCapital"/gt;  lt;/xsl:whengt;  lt;xsl:when test="$allLowersSkiptLength=0"gt;  lt;xsl:commentgt;All Lowerslt;/xsl:commentgt;  lt;xsl:value-of select="$firstCapital"/gt;  lt;/xsl:whengt;  lt;xsl:otherwisegt;  lt;xsl:commentgt;Contains a combination of Lowers and Upperslt;/xsl:commentgt;  lt;xsl:value-of select="."/gt;  lt;/xsl:otherwisegt;  lt;/xsl:choosegt;  lt;/xsl:copygt;  lt;/xsl:templategt;  lt;/xsl:stylesheetgt;  

При использовании в этом xml:

 lt;?xml version="1.0" encoding="UTF-8"?gt; lt;namesgt;  lt;namegt;MacDonaldMet1lt;/namegt;  lt;namegt;McDermottlt;/namegt;  lt;namegt;ALLCAPITALlt;/namegt;  lt;namegt;alllowerlt;/namegt;  lt;namegt;Firstcapitallt;/namegt;  lt;namegt;MacDonaldlt;/namegt; lt;/namesgt;  

Дает такой результат:

 lt;?xml version="1.0" encoding="UTF-8"?gt; lt;namesgt;  lt;namegt;lt;!--Org: MacDonaldMet1--gt;lt;!--Contains Number--gt;MacDonaldMet1lt;/namegt;  lt;namegt;lt;!--Org: McDermott--gt;lt;!--Contains a combination of Lowers and Uppers--gt;McDermottlt;/namegt;  lt;namegt;lt;!--Org: ALLCAPITAL--gt;lt;!--All Uppers--gt;Allcapitallt;/namegt;  lt;namegt;lt;!--Org: alllower--gt;lt;!--All Lowers--gt;Alllowerlt;/namegt;  lt;namegt;lt;!--Org: Firstcapital--gt;lt;!--Already Correct--gt;Firstcapitallt;/namegt;  lt;namegt;lt;!--Org: MacDonald--gt;lt;!--Contains a combination of Lowers and Uppers--gt;MacDonaldlt;/namegt; lt;/namesgt;