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(Something a,something 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)
方法(某事,某事b)
I could not achieve this using the standard substring/substring-after functions.
我无法使用标准的substring / substring-after函数实现此目的。
Is there an easy way to do this?
是否有捷径可寻?
3 个解决方案
#1
19
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() function and simply select the last item in the sequence:
在XSLT 2.0中,您可以使用tokenize()函数,只需选择序列中的最后一项:
tokenize('M:Namespace.Class.Method(Something a, Something b)','\.')[last()]
#2
1
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()函数的任何调用。相反,在每一步中,只比较字符串的一个字符与点字符的相等性。因为最多有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)。
#3
-1
If you do know that you have exactly two dots in your strings then you can try:
如果您确实知道字符串中只有两个点,那么您可以尝试:
<xsl:value-of select="substring-after(substring-after($str, '.'), '.')" />
#1
19
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() function and simply select the last item in the sequence:
在XSLT 2.0中,您可以使用tokenize()函数,只需选择序列中的最后一项:
tokenize('M:Namespace.Class.Method(Something a, Something b)','\.')[last()]
#2
1
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()函数的任何调用。相反,在每一步中,只比较字符串的一个字符与点字符的相等性。因为最多有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)。
#3
-1
If you do know that you have exactly two dots in your strings then you can try:
如果您确实知道字符串中只有两个点,那么您可以尝试:
<xsl:value-of select="substring-after(substring-after($str, '.'), '.')" />