簡體   English   中英

在 xslt 中查找字符串中子字符串的出現次數

[英]Find the number of occurences of a substring in a string in xslt

我正在編寫一個腳本來查找 XSLT 中字符串中子字符串的出現次數。 當我想在超過 20 萬條記錄中遍歷它時花費了太多時間。 任何人都可以幫助我指出一些更改以使其更快,或者以其他方式獲得出現次數?

我說的是一個子字符串,而不是一個字符——所以我不是在談論translate()函數。

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:template match="/">
    <Root>
      <NoofOccurane>
        <xsl:call-template name="GetNoOfOccurance">
          <xsl:with-param name="String" select="'My Name is Rohan and My Home name is also Rohan but one of my firend honey name is also Rohan'"/>
          <xsl:with-param name="SubString" select="'Rohan'"/>
        </xsl:call-template>
      </NoofOccurane>
      <NoofOccurane>
        <xsl:call-template name="GetNoOfOccurance">
          <xsl:with-param name="String" select="'My Name is Rohan and My Home name is also Rohan but one of my firend honey name is also Rohan'"/>
          <xsl:with-param name="SubString" select="'Sohan'"/>
        </xsl:call-template>
      </NoofOccurane>
      <NoofOccurane>
        <xsl:call-template name="GetNoOfOccurance">
          <xsl:with-param name="String" select="'My Name is Rohan and My Home name is also Mohan but one of my firend honey name is also Rohan'"/>
          <xsl:with-param name="SubString" select="'Mohan'"/>
        </xsl:call-template>
      </NoofOccurane>
    </Root>
  </xsl:template>

  <xsl:template name="GetNoOfOccurance">
    <xsl:param name="String"/>
    <xsl:param name="SubString"/>
    <xsl:variable name ="LenString" select="string-length($String)" />
    <xsl:variable name ="LenSubString" select="string-length($SubString)" />
    <xsl:variable name ="ReplaceString">
      <xsl:call-template name="replace-string">
        <xsl:with-param name="text" select="$String"/>
        <xsl:with-param name="replace" select="$SubString"/>
        <xsl:with-param name="with" select="''"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name ="NewLenString" select="string-length($ReplaceString)" />
    <xsl:variable name ="DiffLens" select ="number($LenString)-number($NewLenString)" />
    <xsl:choose>
      <xsl:when test ="$NewLenString=0 and $LenSubString &gt;0">
        <xsl:value-of select ="1"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select ="number($DiffLens) div number($LenSubString)"/>
      </xsl:otherwise>
    </xsl:choose>    
  </xsl:template>

  <!-- Template to Replace function -->
  <xsl:template name="replace-string">
    <xsl:param name="text"/>
    <xsl:param name="replace"/>
    <xsl:param name="with"/>
    <xsl:choose>
      <xsl:when test="contains($text,$replace)">
        <xsl:value-of select="substring-before($text,$replace)"/>
        <xsl:value-of select="$with"/>
        <xsl:call-template name="replace-string">
          <xsl:with-param name="text" select="substring-after($text,$replace)"/>
          <xsl:with-param name="replace" select="$replace"/>
          <xsl:with-param name="with" select="$with"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

結果是

<Root>
  <NoofOccurane>3</NoofOccurane>
  <NoofOccurane>0</NoofOccurane>
  <NoofOccurane>1</NoofOccurane>
</Root>

我提議:

<xsl:template name="GetNoOfOccurance">
  <xsl:param name="String"/>
  <xsl:param name="SubString"/>
  <xsl:param name="Counter" select="0" />

  <xsl:variable name="sa" select="substring-after($String, $SubString)" />

  <xsl:choose>
    <xsl:when test="$sa != '' or contains($String, $SubString)">
      <xsl:call-template name="GetNoOfOccurance">
        <xsl:with-param name="String"    select="$sa" />
        <xsl:with-param name="SubString" select="$SubString" />
        <xsl:with-param name="Counter"   select="$Counter + 1" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$Counter" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

這個 XSLT 1.0 解決方案通過使用簡單直接的遞歸來計算子字符串的出現次數。 不需要進一步的模板,結果就是想要的:

<Root>
  <NoofOccurane>3</NoofOccurane>
  <NoofOccurane>0</NoofOccurane>
  <NoofOccurane>1</NoofOccurane>
</Root>

您可以刪除您的<xsl:template name="replace-string">並放入我的模板中。 無需進一步更改代碼,調用約定相同。

http://www.xsltfunctions.com/xsl/functx_number-of-matches.html

記錄在案:

count(tokenize($arg,$pattern)) - 1

我會把它寫成:

count(tokenize($string,$substring)) - 1

在你的情況下:

count(tokenize('My Name is Rohan and My Home name is also Rohan but one of my firend honey name is also Rohan','Rohan')) - 1

PS:你拼錯了“朋友”。

我在 XSLT 2.0 版中針對我自己的用例測試了此方法,根據文檔,它可能也適用於 1.0 不確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM