如何在 XSLT 中将字符串格式化为 Pascal 大小写?

发布于 2024-08-29 05:07:27 字数 255 浏览 9 评论 0原文

我正在尝试在 XSLT 中格式化字符串,这些字符串需要采用帕斯卡大小写才能正确用于我正在使用的应用程序。

例如:

this_text 将变为 ThisText
this_long_text 将变为 ThisLongText

是否也可以进行设置,以便我可以将输入发送到格式,这样我就不必多次重新创建格式?

I'm trying to format strings in XSLT that needs to be in pascal case to be used appropriately for the application I'm working with.

For example:

this_text would become ThisText
this_long_text would become ThisLongText

Is it possible to also set this up where I can send an input to the format so I do not have to recreate the format multiple times?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

南城追梦 2024-09-05 05:07:27

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:call-template name="Pascalize">
   <xsl:with-param name="pText" select="concat(., '_')"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="Pascalize">
  <xsl:param name="pText"/>

  <xsl:if test="$pText">
   <xsl:value-of select=
    "translate(substring($pText,1,1), $vLower, $vUpper)"/>

   <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

   <xsl:call-template name="Pascalize">
     <xsl:with-param name="pText"
       select="substring-after(substring($pText,2), '_')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于此 XML 文档时

<t>
  <a>this_text</a>
  <b>this_long_text</b>
</t>

产生所需的结果

<t>
    <a>ThisText</a>
    <b>ThisLongText</b>
</t>

顺便说一句,这是camelCase,这是是 PascalCase

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:call-template name="Pascalize">
   <xsl:with-param name="pText" select="concat(., '_')"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="Pascalize">
  <xsl:param name="pText"/>

  <xsl:if test="$pText">
   <xsl:value-of select=
    "translate(substring($pText,1,1), $vLower, $vUpper)"/>

   <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

   <xsl:call-template name="Pascalize">
     <xsl:with-param name="pText"
       select="substring-after(substring($pText,2), '_')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<t>
  <a>this_text</a>
  <b>this_long_text</b>
</t>

produces the desired result:

<t>
    <a>ThisText</a>
    <b>ThisLongText</b>
</t>

BTW, this is camelCase and this is PascalCase

彻夜缠绵 2024-09-05 05:07:27

两年后,这是一个 XSLT 2.0 解决方案:

<xsl:function name="fn:pascal-case">
    <xsl:param name="string"/>
    <xsl:value-of select="string-join(for $s in tokenize($string,'\W+') return concat(upper-case(substring($s,1,1)),substring($s,2)),'')"/>
</xsl:function>

它将 'this_long_text' 或 'this-long-text' 帕斯卡化为 'ThisLongText',因为它会在任何非单词字符上中断。

在我最熟悉的正则表达式风格(perl、pcre 等)中,下划线被视为 '\w' 字符类的一部分(因此不是 \W 的一部分),但对于 XSLT 2.0,使用 XSD 数据类型( http://www.w3.org/TR/xmlschema-2/) 和 '\w' 定义为:

[#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters)

所以 '\W' 包含下划线。

Here, two years after the fact, is an XSLT 2.0 solution:

<xsl:function name="fn:pascal-case">
    <xsl:param name="string"/>
    <xsl:value-of select="string-join(for $s in tokenize($string,'\W+') return concat(upper-case(substring($s,1,1)),substring($s,2)),'')"/>
</xsl:function>

It will pascalize either 'this_long_text' or 'this-long-text' to 'ThisLongText' because it breaks on any non-word characters.

In the regex flavors I am most familiar with (perl, pcre, etc.), an underscore is considered part of the '\w' character class (therefore not part of \W), but for XSLT 2.0 the XSD datatypes are used (http://www.w3.org/TR/xmlschema-2/) and '\w' is defined as:

[#x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] (all characters except the set of "punctuation", "separator" and "other" characters)

so '\W' includes an underscore.

毅然前行 2024-09-05 05:07:27

这个版本对我有用。我添加了一个选择,当不再存在下划线时,输出字符串的“其余部分”。

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="Pascalize">
    <xsl:param name="pText" />
    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)" />
        <xsl:choose>
            <xsl:when test="contains($pText, '_')"> 
                <xsl:value-of select="substring-before(substring($pText,2), '_')" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="substring($pText,2)" />
            </xsl:otherwise>
        </xsl:choose>
        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

另外,如果有人来这里寻找反向过程(我今天碰巧也需要这个过程,并且在任何地方都找不到没有一个例子)......

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="TitleCase">
    <xsl:param name="pText" />
    <xsl:call-template name="TitleCase_recurse">
        <xsl:with-param name="pText" select="concat(translate(substring($pText,1,1), $vLower, $vUpper), substring($pText,2))" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="TitleCase_recurse">
    <xsl:param name="pText" />
    <xsl:if test="string-length($pText) > 1">
        <xsl:if test="not(substring($pText,1,1) = ' ' and substring($pText,1,1) = ' ')">
            <xsl:value-of select="substring($pText,1,1)" />
        </xsl:if>
        <xsl:if test="translate(substring($pText,1,1), $vLower, $vUpper) != substring($pText,1,1)">
            <xsl:if test="translate(substring($pText,2,1), $vLower, $vUpper) = substring($pText,2,1)">
                <xsl:text> </xsl:text>
            </xsl:if>
        </xsl:if>
        <xsl:call-template name="TitleCase_recurse">
            <xsl:with-param name="pText" select="substring($pText,2)" />
        </xsl:call-template>
    </xsl:if>
    <xsl:if test="string-length($pText) = 1">
        <xsl:value-of select="$pText" />
    </xsl:if>
</xsl:template>

我喜欢它当我完全有意识地放弃几个小时后,我的潜意识大脑就会弹出一个答案。 ;-)

This version worked for me. I added a choose that outputs "the rest" of the string when no more underbars are present.

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="Pascalize">
    <xsl:param name="pText" />
    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)" />
        <xsl:choose>
            <xsl:when test="contains($pText, '_')"> 
                <xsl:value-of select="substring-before(substring($pText,2), '_')" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="substring($pText,2)" />
            </xsl:otherwise>
        </xsl:choose>
        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

Also, in case anyone comes here looking for the reverse process (which I happened to also require today and could find not a single example of anywhere)...

<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

<xsl:template name="TitleCase">
    <xsl:param name="pText" />
    <xsl:call-template name="TitleCase_recurse">
        <xsl:with-param name="pText" select="concat(translate(substring($pText,1,1), $vLower, $vUpper), substring($pText,2))" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="TitleCase_recurse">
    <xsl:param name="pText" />
    <xsl:if test="string-length($pText) > 1">
        <xsl:if test="not(substring($pText,1,1) = ' ' and substring($pText,1,1) = ' ')">
            <xsl:value-of select="substring($pText,1,1)" />
        </xsl:if>
        <xsl:if test="translate(substring($pText,1,1), $vLower, $vUpper) != substring($pText,1,1)">
            <xsl:if test="translate(substring($pText,2,1), $vLower, $vUpper) = substring($pText,2,1)">
                <xsl:text> </xsl:text>
            </xsl:if>
        </xsl:if>
        <xsl:call-template name="TitleCase_recurse">
            <xsl:with-param name="pText" select="substring($pText,2)" />
        </xsl:call-template>
    </xsl:if>
    <xsl:if test="string-length($pText) = 1">
        <xsl:value-of select="$pText" />
    </xsl:if>
</xsl:template>

I love it when my subconscious brain pops up an answer a few hours after I've completely given up consciously. ;-)

巾帼英雄 2024-09-05 05:07:27

我试图通过以下 XLST 函数调用来实现“帕斯卡化”:

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\U$1')"/>

不幸的是,处理器抛出错误消息“replace() 中的替换字符串无效:
\ 字符后面必须跟 \ 或 $"

问题是 \U 修饰符,它应该对匹配的模式进行大写转换。如果我将其更改为

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\\U$1')"/>

输出字符串包含序列 '\U' 因为它现在已被转义- 但我不想逃避它,我希望它有效;-) 我做了测试

<xsl:value-of select="fn:replace(@name,'_(\w{1})','$1')"/>

(没有将匹配转换为大写)并且效果很好,但当然它没有大写,只是删除下划线并替换。下划线后面的字母本身而不是大写。我在这里做错了什么吗?或者我的 XSLT 处理器的正则表达式实现根本不支持 \U 修饰符?

I was trying to achieve the "pascalizing" with the following XLST function call:

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\U$1')"/>

Unfortunately the processor throws the error message "Invalid replacement string in replace():
\ character must be followed by \ or $"

the problem is the \U modifier which is supposed to do the uppercase conversion of the matched pattern. If I change it to

<xsl:value-of select="fn:replace(@name,'_(\w{1})','\\U$1')"/>

the output string contains the sequence '\U' because it is now esacped - but I don't want to escape it, I want it do be effective ;-) . I did test

<xsl:value-of select="fn:replace(@name,'_(\w{1})','$1')"/>

(without converting the match to uppercase) and that works fine. But of course it does no uppercasing, just removes underscores and replaces the letter after the underscore by itself instead of capitalizing it. Am I doing something wrong here or is the \U modifier simply not supported in the regex implementation of my XSLT processor?

回忆追雨的时光 2024-09-05 05:07:27

感谢 Dimitre,我才能够顺利完成大部分任务。当通过 Pascalize 模板运行我的字符串时,最后一个“_”后面的位被切断。可能有一种更简洁的方法,但这是我使用的代码:

<xsl:template name="Pascalize">
    <xsl:param name="pText"/>

    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)"/>

        <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')"/>
        </xsl:call-template>

        <xsl:call-template name="GrabLastPart">
            <xsl:with-param name="pText" select="$pText"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="GrabLastPart">
    <xsl:param name="pText"/>

    <xsl:choose>
        <xsl:when test="contains($pText, '_')">
            <xsl:call-template name="GrabLastPart">
                <xsl:with-param name="pText" expr="substring-after($pText, '_')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="substring($pText, 2)"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Thanks to Dimitre, I was able to get most of the way there. When running my strings through the Pascalize template, the bit after the last '_' was cut off. There's probably a cleaner way of doing it, but here's the code I used:

<xsl:template name="Pascalize">
    <xsl:param name="pText"/>

    <xsl:if test="$pText">
        <xsl:value-of select="translate(substring($pText,1,1), $vLower, $vUpper)"/>

        <xsl:value-of select="substring-before(substring($pText,2), '_')"/>

        <xsl:call-template name="Pascalize">
            <xsl:with-param name="pText" select="substring-after(substring($pText,2), '_')"/>
        </xsl:call-template>

        <xsl:call-template name="GrabLastPart">
            <xsl:with-param name="pText" select="$pText"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="GrabLastPart">
    <xsl:param name="pText"/>

    <xsl:choose>
        <xsl:when test="contains($pText, '_')">
            <xsl:call-template name="GrabLastPart">
                <xsl:with-param name="pText" expr="substring-after($pText, '_')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="substring($pText, 2)"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文