XSLT 搜索和替换标点符号

XSLT search and replace punctuation mark

我有一个 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{}

\commadash{}

{–

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

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

问题是 . 在正则表达式中很特殊。所以 <search>.–</search> 将匹配任何后跟 -.

的字符

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

<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="Whosebug 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,它将替换示例中的 {–