5

是否可以在从小写到大写边界拆分标签,例如,标签“UserLicenseCode”应该转换为“User License Code”,以便列标题看起来更好一些。

我过去使用 Perl 的正则表达式做过类似的事情,但 XSLT 对我来说是一个全新的球类游戏。

在创建这样一个模板的任何指针将不胜感激!

谢谢克里希纳

4

2 回答 2

2

使用递归,可以遍历 XSLT 中的字符串来评估每个字符。为此,请创建一个仅接受一个字符串参数的新模板。检查第一个字符,如果是大写字符,写一个空格。然后写字。然后使用单个字符串中的剩余字符再次调用模板。这将导致您想要做的事情。

那将是你的指针。我需要一些时间来制定模板。:-)


它进行了一些测试,尤其是为了获得整个事物内部的空间。(我为此误用了一个字符!)但是这段代码应该给你一个想法......

我使用了这个 XML:

<?xml version="1.0" encoding="UTF-8"?>
<blah>UserLicenseCode</blah>

然后这个样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="text"/>
    <xsl:variable name="Space">*</xsl:variable>
    <xsl:template match="blah">
    <xsl:variable name="Split">
        <xsl:call-template name="Split">
            <xsl:with-param name="Value" select="."/>
            <xsl:with-param name="First" select="true()"/>
        </xsl:call-template></xsl:variable>
        <xsl:value-of select="translate($Split, '*', ' ')" />
    </xsl:template>
    <xsl:template name="Split">
        <xsl:param name="Value"/>
        <xsl:param name="First" select="false()"/>
        <xsl:if test="$Value!=''">
            <xsl:variable name="FirstChar" select="substring($Value, 1, 1)"/>
            <xsl:variable name="Rest" select="substring-after($Value, $FirstChar)"/>
                <xsl:if test="not($First)">
                    <xsl:if test="translate($FirstChar, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '..........................')= '.'">
                        <xsl:value-of select="$Space"/>
                    </xsl:if>
                </xsl:if>
                <xsl:value-of select="$FirstChar"/>
                <xsl:call-template name="Split">
                    <xsl:with-param name="Value" select="$Rest"/>
                </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

我得到了这个结果:

User License Code

请记住,空格和其他空白字符确实会从 XML 中删除,这就是我使用“*”代替的原因,我将其转换为空格。

当然,这段代码可以改进。这是我可以在 10 分钟的工作中得出的结论。在其他语言中,它需要更少的代码行,但在 XSLT 中,考虑到它包含的代码行数量,它仍然相当快。

于 2009-09-13T21:34:47.940 回答
1

XSLT + FXSL 解决方案(在 XSLT 2.0 中,但几乎相同的代码适用于 XSLT 1.0 和 FXSL 1.x

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:testmap="testmap"
exclude-result-prefixes="f testmap"
>
   <xsl:import href="../f/func-str-dvc-map.xsl"/>
   <testmap:testmap/>

   <xsl:output omit-xml-declaration="yes" indent="yes"/>

   <xsl:template match="/">
     <xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>

     '<xsl:value-of select="f:str-map($vTestMap, 'UserLicenseCode')"
       />'
   </xsl:template>

    <xsl:template name="mySplit" match="*[namespace-uri() = 'testmap']"
     mode="f:FXSL">
      <xsl:param name="arg1"/>

      <xsl:value-of select=
       "if(lower-case($arg1) ne $arg1)
         then concat(' ', $arg1)
         else $arg1
       "/>
    </xsl:template>
</xsl:stylesheet>

当对任何源 XML 文档(未使用)应用上述转换时,将产生预期的正确结果:

'用户许可证代码'

请注意

  1. 我们使用的是 FXSL 函数/模板的 DVC 版本str-map()。这是一个高阶函数 (HOF),它接受两个参数:另一个函数和一个字符串。str-map()将函数应用于字符串的每个字符并返回结果的串联。

  2. 因为使用了 lower-case() 函数(在 XSLT 2.0 版本中),我们不仅限于拉丁字母。

于 2009-09-14T13:45:32.673 回答