【问题标题】:How to add zero-width space after every third uppercase letter in XSLT?如何在 XSLT 中每三个大写字母后添加零宽度空格?
【发布时间】:2016-02-01 15:23:17
【问题描述】:

我想在 XSLT 中每隔三个大写字母后添加零宽度空格。 在这里,我想选择文档中的所有文本节点,并在这些文本节点中过滤大写单词。

我的 XML 示例代码是:

<doc>
    <front>
        <lable>this is a TEST TEXT</lable>
        <para>This is a TEST TEXT with UPPER and Lower</para>
    </front>
    <middle>
        <lable>this is a TEST TEXT</lable>
        <para>This is a TEST TEXT with UPPER and Lower</para>
    </middle>
    <back>
        <lable>This is a TEST TEXT</lable>
        <para>This is a TEST TEXT with UPPER and Lower</para>
    </back>
</doc>

我写的 XSLT 是:

<xsl:template match="*/text()" priority="100">
        <xsl:analyze-string select="." regex="^[A-Z]+">
            <xsl:matching-substring>
                <xsl:variable name="upperWord" select="substring(.,3)"/>
                <xsl:value-of select="concat($upperWord,'&#x200b;')"/>
            </xsl:matching-substring>

            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>

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

我期待的输出:

<doc>
            <front>
                <lable>this is a TES&#x200b;T TEX&#x200b;T</lable>
                <para>​his is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
            </front>
            <front>
                <lable>this is a TES&#x200b;T TEX&#x200b;T</lable>
                <para>​his is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
            </front>
            <front>
                <lable>this is a TES&#x200b;T TEX&#x200b;T</lable>
                <para>​his is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
            </front>
        </doc>

    Output I got:

<doc>
        <front>
            <lable>this is a TEST TEXT</lable>
            <para>​his is a TEST TEXT with UPPER and Lower</para>
        </front>
        <middle>
            <lable>this is a TEST TEXT</lable>
            <para>​his is a TEST TEXT with UPPER and Lower</para>
        </middle>
        <back>
            <lable>​his is a TEST TEXT</lable>
            <para>​his is a TEST TEXT with UPPER and Lower</para>
        </back>
    </doc>

在这里,我无法理解为什么选择了单词的大写首字母以及为什么没有选择所有文本节点。 有人可以帮我解决这个问题.. 谢谢..

【问题讨论】:

    标签: regex xslt-2.0


    【解决方案1】:

    尝试替换

    regex="^[A-Z]+"
    

    regex="[A-Z]+"
    

    【讨论】:

    • 感谢 Vegenta..regex 通过替换它运行良好..但我的问题还没有完全解决
    【解决方案2】:

    您应该能够通过删除xsl:analyze-string 并仅使用replace() 来简化它。

    注意:在我的示例中,我使用xsl:character-map 来保留文本中的实体。你可以去掉它,然后插入实际的字符。

    示例... (working version here)

    XML 输入

    <doc>
        <front>
            <lable>this is a TEST TEXT</lable>
            <para>This is a TEST TEXT with UPPER and Lower</para>
        </front>
        <middle>
            <lable>this is a TEST TEXT</lable>
            <para>This is a TEST TEXT with UPPER and Lower</para>
        </middle>
        <back>
            <lable>This is a TEST TEXT</lable>
            <para>This is a TEST TEXT with UPPER and Lower</para>
        </back>
    </doc>
    

    XSLT 2.0

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes" use-character-maps="chars"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:character-map name="chars">
        <xsl:output-character character="&#x200b;" string="&amp;#x200b;"/>
      </xsl:character-map>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="text()" priority="1">
          <xsl:value-of select="replace(.,'([A-Z]{3})','$1&#x200b;')"/>
      </xsl:template>
    
    </xsl:stylesheet>
    

    XML 输出

    <doc>
       <front>
          <lable>this is a TES&#x200b;T TEX&#x200b;T</lable>
          <para>This is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
       </front>
       <middle>
          <lable>this is a TES&#x200b;T TEX&#x200b;T</lable>
          <para>This is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
       </middle>
       <back>
          <lable>This is a TES&#x200b;T TEX&#x200b;T</lable>
          <para>This is a TES&#x200b;T TEX&#x200b;T with UPP&#x200b;ER and Lower</para>
       </back>
    </doc>
    

    【讨论】:

    • 谢谢..这是有效的..你能解释一下为什么这个 xsl:analyze-string 给了我不正确的解决方案吗?
    • @user2490093 - 这是因为您的正则表达式匹配一个或多个锚定到字符串开头的大写字母。然后使用substring() 从匹配的第三个字符开始。因此,如果字符串以 This 开头,则匹配只是 T 并且从第三个字符开始的子字符串不返回任何内容。零宽度空间正在输出;你只是看不到它。
    • @user2490093 - 如果您仍然想要xsl:analyze-string 答案,请告诉我。否则,如果这个答案足够,请点击旁边的复选标记(✅)接受它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多