C# 在 XSLT 中最后一次出现字符后获取子字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9078779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 05:48:23  来源:igfitidea点击:

Getting a substring AFTER the last occurrence of a character in XSLT

c#xmlxslt

提问by lysergic-acid

I have a string in an XML file that looks similar to this:

我在 XML 文件中有一个类似于以下内容的字符串:

M:Namespace.Class.Method(Something a, Something b)

M:Namespace.Class.Method(某事a,某事b)

The number of period (.) characters is abritrary, meaning it can be only 2 as in this example, but can be more.

句点 (.) 字符的数量是随机的,这意味着它在本例中只能是 2 个,但也可以更多。

I would like to use XSLT to get a substring of this string from the last '.' character, so that i will only be left with:

我想使用 XSLT 从最后一个 '.' 中获取此字符串的子字符串。字符,所以我只会留下:

Method(Something a, Something b)

方法(某事a,某事b)

I could not achieve this using the standard substring/substring-after functions.

我无法使用标准的 substring/substring-after 函数来实现这一点。

Is there an easy way to do this?

是否有捷径可寻?

采纳答案by Mads Hansen

In XSLT 1.0 you will need to use a recursive template, like this:

在 XSLT 1.0 中,您需要使用递归模板,如下所示:

  <xsl:template name="substring-after-last">
    <xsl:param name="string" />
    <xsl:param name="delimiter" />
    <xsl:choose>
      <xsl:when test="contains($string, $delimiter)">
        <xsl:call-template name="substring-after-last">
          <xsl:with-param name="string"
            select="substring-after($string, $delimiter)" />
          <xsl:with-param name="delimiter" select="$delimiter" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise><xsl:value-of 
                  select="$string" /></xsl:otherwise>
    </xsl:choose>
  </xsl:template>

and invoke it like this:

并像这样调用它:

<xsl:call-template name="substring-after-last">
  <xsl:with-param name="string" select="'M:Namespace.Class.Method(Something a, Something b)'" />
  <xsl:with-param name="delimiter" select="'.'" />
</xsl:call-template>

In XSLT 2.0, you can use the tokenize()functionand simply select the last item in the sequence:

在 XSLT 2.0 中,您可以使用tokenize()函数并简单地选择序列中的最后一项:

tokenize('M:Namespace.Class.Method(Something a, Something b)','\.')[last()]

回答by Igor Korkhov

If you do know that you have exactly twodots in your strings then you can try:

如果您确实知道字符串中恰好有两个点,那么您可以尝试:

<xsl:value-of select="substring-after(substring-after($str, '.'), '.')" /> 

回答by Dimitre Novatchev

Here is a more efficient solution O(N) vs. O(N^2) for the accepted answer:

对于已接受的答案,这是 O(N) 与 O(N^2) 的更有效的解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="text()" name="skipAfterDots">
  <xsl:param name="pTotalString" select="."/>
  <xsl:param name="pTotalLength" select="string-length(.)"/>
  <xsl:param name="pPosition" select="1"/>
  <xsl:param name="pLastFound" select="-1"/>

  <xsl:choose>
    <xsl:when test="$pPosition > $pTotalLength">
      <xsl:value-of select="substring($pTotalString, $pLastFound + 1)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="vIsDot" select=
       "substring($pTotalString, $pPosition, 1) = '.'"/>

      <xsl:call-template name="skipAfterDots">
        <xsl:with-param name="pTotalString" select="$pTotalString"/>
        <xsl:with-param name="pTotalLength" select="$pTotalLength"/>
        <xsl:with-param name="pLastFound" select=
        "$pLastFound * not($vIsDot) + $pPosition * $vIsDot"/>
        <xsl:with-param name="pPosition" select="$pPosition+1"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

当此转换应用于以下 XML 文档时

<t>M:Namespace.Class.Method(Something a, Something b)</t>

the wanted, correct result is produced:

产生了想要的、正确的结果

Method(Something a, Something b)

Explanation:

说明

This solution doesn't contain any call to the substring-after()function. Instead, at each step only the one character of the string is compared for equality with the dot character. Because there are at most N characters, this is O(N) -- linear complexity.

此解决方案不包含对substring-after()function 的任何调用。相反,在每个步骤中,仅将字符串的一个字符与点字符进行比较。因为最多有 N 个字符,所以这是 O(N) —— 线性复杂度。

On the contrary, the accepted answer calls the substring-after()function on every step. In the worst case there could be N dots and thus this would be O(N^N) -- quadratic complexity.

相反,接受的答案会substring-after()在每一步调用函数。在最坏的情况下可能有 N 个点,因此这将是 O(N^N) - 二次复杂度。

Note: We make the reasonable assumption that in both solutions locating the k-th character of a string is O(1).

注意:我们做出了合理的假设,即在两个解决方案中,定位字符串的第 k 个字符都是 O(1)。