如何使用 XSLT 删除第一次出现的单词?

How to remove the first occurrence of a word with XSLT?

给定以下 XML 文档:

<books>
  <book>
   <name>The problem of the ages</name>
  </book>
  <book>
   <name>Filtering the tap</name>
  </book>
  <book>
   <name>Legend of Atlantis</name>
  </book>
</books>

我想去掉每本书名中的第一个“the”。输出示例:

<library>
  <record>problem of the ages</record>
  <record>Filtering tap</record>
  <record>Legend of Atlantis</record>
</library>

我如何使用单个 XSLT 实现此目的?

鉴于世界上存在不同的语言,很难确定一个词是什么。但是,XSLT/XPath 2 及更高版本中使用的正则表达式语言允许您匹配 \w 字母数字字母,因此

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="word-to-eliminate" as="xs:string" select="'the'"/>
  
  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="book/name">
      <xsl:copy>
          <xsl:apply-templates select="analyze-string(., $word-to-eliminate, 'i')" mode="eliminate-first"/>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="fn:match[1]" mode="eliminate-first"/>
  
  <xsl:template match="fn:non-match[preceding-sibling::node()[1][. is root()/descendant::fn:match[1]]]" mode="eliminate-first">
      <xsl:value-of select="replace(., '^\s', '')"/>
  </xsl:template>

</xsl:stylesheet>

可能对 XSLT 3 有所帮助,或者可以在 XSLT 2 中使用 xsl:analyze-string 以类似的方式实现。

或者,如果任何白色 space 都可以被视为单词分隔符,并且在结果中您只希望在剩余的单词之间有一个 space,那么

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="word-to-eliminate" as="xs:string" select="'the'"/>
  
  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="book">
      <record>
          <xsl:value-of 
            select="analyze-string(name, '\s+')
                    !
                    (fn:non-match 
                     except 
                     fn:non-match[lower-case(.) = $word-to-eliminate][1]
                    )"/>
      </record>
  </xsl:template>
  
</xsl:stylesheet>