【问题标题】:XSLT search and replace punctuation markXSLT 搜索和替换标点符号
【发布时间】:2017-01-31 15:03:52
【问题描述】:

我有一个 XSLT 级联将 XML 传输到 TeX。在最后一步中,我有一个简单的 xml 文件,其中包含两个标签之间的所有文本,我想应用几个搜索和替换例程。

所以输入文件是这样的:

<start>
    .–
    ,–
    {– 
</start>

与此 XSLT 一起应用时(或多或少逐字逐句取自 Replacing strings in various XML files

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="list">
        <words>
             <word>
            <search> / </search>
            <replace>\allowbreak\,\slash\,\allowbreak{}</replace>
        </word>
        <word>
            <search>.–</search>
            <replace>{\dotdash}</replace>
        </word>
        <word>
            <search>,–</search>
            <replace>{\commadash}</replace>
        </word>
        <word>
            <search>;–</search>
            <replace>{\semicolondash}</replace>
        </word>
        <word>
            <search>!–</search>
            <replace>{\excdash}</replace>
        </word>
        </words>
    </xsl:param>
    
    <xsl:template match="@*|*|comment()|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="text()">
        <xsl:variable name="search" select="concat('(',string-join($list/words/word/search,'|'),')')"/>
        <xsl:analyze-string select="." regex="{$search}">
            <xsl:matching-substring>
                <xsl:value-of select="$list/words/word[search=current()]/replace"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>
</xsl:stylesheet>

应该有以下输出:

\dotdash{}

\逗号{}

{–

不幸的是,“{–”似乎触发了什么并消失了。谁能解释一下为什么?

【问题讨论】:

    标签: xslt replace punctuation


    【解决方案1】:

    很高兴您链接到的原始答案有所帮助。如果您还没有投票,请考虑投票。 ;-)

    问题是. 在正则表达式中很特殊。所以&lt;search&gt;.–&lt;/search&gt; 将匹配任何后跟- 的字符。

    您应该在搜索变量中转义 .

    <xsl:variable name="search" select="replace(concat('(',string-join($list/words/word/search,'|'),')'),'\.','\\.')"/>
    

    您还需要转义任何其他特殊的正则表达式字符,因此您可以考虑创建一个xsl:function 以简化该部分。

    这是一个函数示例,它将转义 .{ 对于初学者...

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:so="stackoverflow example" exclude-result-prefixes="so">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
      <xsl:param name="list">
        <words>
          <word>
            <search> / </search>
            <replace>\allowbreak\,\slash\,\allowbreak{}</replace>
          </word>
          <word>
            <search>.–</search>
            <replace>{\dotdash}</replace>
          </word>
          <word>
            <search>,–</search>
            <replace>{\commadash}</replace>
          </word>
          <word>
            <search>;–</search>
            <replace>{\semicolondash}</replace>
          </word>
          <word>
            <search>!–</search>
            <replace>{\excdash}</replace>
          </word>
          <!--<word>
            <search>{–</search>
            <replace>bam!</replace>
          </word>-->
        </words>
      </xsl:param>
    
      <xsl:function name="so:escapeRegex">
        <xsl:param name="regex"/>
        <xsl:analyze-string select="$regex" regex="\.|\{{">
          <xsl:matching-substring>
            <xsl:value-of select="concat('\',.)"/>
          </xsl:matching-substring>
          <xsl:non-matching-substring>
            <xsl:value-of select="."/>
          </xsl:non-matching-substring>
        </xsl:analyze-string>
      </xsl:function>
    
      <xsl:template match="@*|*|comment()|processing-instruction()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="text()">
        <xsl:variable name="search" select="so:escapeRegex(concat('(',string-join($list/words/word/search,'|'),')'))"/>
        <xsl:analyze-string select="." regex="{$search}">
          <xsl:matching-substring>
            <xsl:message>"<xsl:value-of select="."/>" matched <xsl:value-of select="$search"/></xsl:message>
            <xsl:value-of select="$list/words/word[search=current()]/replace"/>
          </xsl:matching-substring>
          <xsl:non-matching-substring>
            <xsl:value-of select="."/>
          </xsl:non-matching-substring>
        </xsl:analyze-string>
      </xsl:template>
    </xsl:stylesheet>
    

    如果您取消注释 list 参数中的最后一个 word,它将替换您示例中的 {–

    【讨论】:

    • 在 XSLT 3.0 中,您可以使用 flags="q" 表示正则表达式中的所有字符都将被视为代表自己。但是当然你不能使用“|”分开备选方案。
    猜你喜欢
    • 2018-08-11
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多