3

使用 xsl 2.0 我试图将所有大写文本转换为每个节点中只有第一个文本字母大写。它们是大量可能的子元素。

<text> text text text
<head>BLAH <unkownTag>BLAH</unkownTag> BLAH </head>
</text>

我想将其转换为阅读

<text> text text text
<head>Blah <unkownTag>Blah</unkownTag> Blah </head>
</text>

我最接近的是

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="head/text()">
    <xsl:value-of select="concat(upper-case(substring(.,1,1)),lower-case(substring(.,2)))"/>        
</xsl:template> 

这给了我结果

<text> text text text 
   <head>Blah <unkownTag>BLAH</unkownTag> blah </head>
</text>

如何在 head 的所有子节点中进行小写转换?

4

4 回答 4

4

无论分隔单词的标点符号如何,这种转换都会产生想要的结果:

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

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

 <xsl:template match="head//text()">
  <xsl:analyze-string select="." regex="\p{{L}}+">
   <xsl:matching-substring>
     <xsl:value-of select=
      "concat(upper-case(substring(.,1,1)), lower-case(substring(.,2)))"/>
   </xsl:matching-substring>
   <xsl:non-matching-substring>
    <xsl:value-of select="."/>
   </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<text> text text text
 <head>BLAH <unkownTag>BLAH</unkownTag> BLAH </head>
</text>

产生了想要的正确结果:

<text> text text text
 <head>Blah <unkownTag>Blah</unkownTag> Blah </head>
</text>

应用于此 XML 文档时:

<text> text text text
 <head>BLAH$<unkownTag>BLAH</unkownTag>-BLAH;</head>
</text>

再次产生正确的结果:

<text> text text text
 <head>Blah$<unkownTag>Blah</unkownTag>-Blah;</head>
</text>

说明

  1. 正确使用<xsl:analyze-string>指令。

  2. 正确使用\p{L}字符类。

  3. 正确使用<xsl:matching-substring><xsl:non-matching-substring>说明。

于 2013-02-27T03:24:59.570 回答
1

您文本中的空格使这是一个有趣的问题。要匹配 'head' 下的所有 text() 节点,请使用 XPath 表达式查看祖先。

在这里,我对字符串进行标记,然后循环遍历结果集,将第一个字符更改为大写,将后面的字符更改为小写。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
   </xsl:template>

   <xsl:template match="text()[ ancestor::head ]">
       <xsl:value-of select="
            for $str in tokenize( ., '\s' ) 
            return concat( upper-case(substring($str,1,1)), 
                           lower-case(substring($str,2)) )"/>
   </xsl:template>
</xsl:stylesheet>
于 2013-02-27T02:15:38.887 回答
0

尝试这个。我还没有测试它,你可能需要稍微调整一下。

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

<xsl:template match="head">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()">
      <xsl:value-of select="concat(upper-case(substring(.,1,1)),lower-case(substring(.,2)))"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>
于 2013-02-27T01:09:48.413 回答
0

这可能会帮助您参与其中。

<xsl:template match="/">
  <xsl:apply-templates select="node()" mode="firstup"/>
</xsl:template>

<xsl:template match="text()" mode="firstup">
  <!--<x>-->
    <xsl:value-of select="concat(upper-case(substring(.,1,1)),lower-case(substring(.,2)))"/>
  <!--</x>-->
</xsl:template>

虽然不确定第三个“BLAH”,但这个 text() 节点以空格开头,因此在使兄弟文本节点大写正确时会增加一些难度。取消注释“x”元素以查看此内容。您可能还想查看规范化空间和 position() 函数以进一步了解。

于 2013-02-27T01:31:21.310 回答