2010-04-15 104 views
10

我想在XSLT中格式化字符串,需要在帕斯卡的情况下适当使用我正在使用的应用程序。如何在XSLT中将字符串格式化为Pascal格式?

例如:

this_text将成为ThisText
this_long_text将成为ThisLongText

是否有可能也设置此,我可以发送输入格式所以我不必重新创建多次格式?

+0

好问题(+1)。查看我的答案以获得完整的XSLT解决方案:) – 2010-04-15 17:39:51

+0

** reverse **过程也可用。请参阅下面的答案。 ;-) – 2010-06-23 05:16:41

回答

8

该转化

<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> 

顺便说一句,这是驼峰这是PascalCase

+0

+1令人印象深刻 - 很好地完成! – 2010-04-15 20:31:59

+0

感谢您的快速响应 - 努力实现它。我同意安德鲁 - 很好地完成! – OpenDataAlex 2010-04-15 20:32:33

+0

快速后续问题 - 我正在构建的转换是将XML文件转换为YAML文件。这似乎影响所有文本,而不仅仅是特定的标题。有没有办法指定我想要通过Pascalize模板运行哪些文本? 再次感谢您带领我走向正确的道路。 – OpenDataAlex 2010-04-15 20:46:52

0

感谢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> 
4

此版本为我工作。我添加了一个选项,在不存在更多下划线时输出字符串的“其余”。

<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) &gt; 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> 

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

+0

很好地完成。总是一个学习过程,这些东西,嘿。 – OpenDataAlex 2010-06-22 16:38:21

1

我试图实现“pascalizing”具有以下XLST函数调用:

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

不幸的是,处理器引发错误信息“无效的替换字符串替换中的(): \字符必须后跟\或$“

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

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

输出字符串包含序列“\ U”,因为它现在esacped - 但我不想逃避它,我希望它也能有效;-)。我做了测试

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

(没有将匹配转换为大写),并且工作正常。但它当然没有大写,只是删除下划线,并将下划线后面的字母替换掉​​而不是大写。我在这里做错了什么,或者是我的XSLT处理器的regex实现中不支持\ U修饰符?

+0

我不是任何一个正则表达式的专家,但我不相信\ U被支持。 – OpenDataAlex 2010-08-09 16:11:39

6

这里,其实两年后,是一个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> 

它将pascalize是“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' 包括下划线。

相关问题