XSLT搜索并替换标点符号

时间:2017-01-31 15:03:52

标签: xslt replace punctuation

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

     

{ -

不幸的是,“{ - ”似乎触发了一些东西并且消失了。任何人都可以解释原因吗?

1 个答案:

答案 0 :(得分:1)

很高兴与你联系的原始答案有所帮助。如果你还没有,请考虑提升。 ; - )

问题是.在正则表达式中很特殊。因此<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="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>

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