有没有办法确定xsl:matching-substring
是否是last()
匹配的子字符串?
示例数据:
<data>
<value>1 A 1 2 B 2 1 C 3</value>
</data>
示例XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:output media-type="xhtml" encoding="UTF-8" />
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>xsl:matching-substring problem</title>
</head>
<body>
<h1>xsl:matching-substring problem</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="//value">
<xsl:element name="p" namespace="http://www.w3.org/1999/xhtml">
<xsl:analyze-string select="." regex="\p{{Nd}}\s\p{{Lu}}\s\p{{Nd}}" flags="i">
<xsl:matching-substring>
<xsl:value-of select="."/>
<xsl:if test="not(last())">
<xsl:element name="br" namespace="http://www.w3.org/1999/xhtml" />
</xsl:if />
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
结果:
<?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="xhtml; charset=UTF-8" />
<title>xsl:matching-substring problem</title>
</head>
<body>
<h1>xsl:matching-substring problem</h1>
<p>1 A 12 B 21 C 3</p>
</body>
</html>
因此,似乎last()
对于第一个和第二个匹配子字符串也是如此(事实上,last()
似乎返回匹配子字符串的最后一个字符的位置。)
没有xsl:if
,我得到:
<?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="xhtml; charset=UTF-8" />
<title>xsl:matching-substring problem</title>
</head>
<body>
<h1>xsl:matching-substring problem</h1>
<p>1 A 1<br />2 B 2<br />1 C 3<br /></p>
</body>
</html>
但我更喜欢<p>1 A 1<br />2 B 2<br />1 C 3</p>
。有没有办法使用XSLT 2.0实现这一目标? (我使用Saxon HE作为xslt引擎)。
答案 0 :(得分:3)
@ Joel_M.Lamsen在您的代码中发现了一个错误,但他的解决方案并不正确。
规范说明:在处理每个子字符串时,子字符串的内容将是上下文项(作为xs:string类型的值);匹配和非匹配子串序列中子串的位置将是上下文位置;匹配和不匹配的子串的数量将是上下文大小。
So(position()= last())测试您是否正在处理最后一个子字符串,该子字符串可以是匹配的子字符串,也可以是不匹配的子字符串。如果你在xsl:matching-substring中,处理最后一个匹配的子字符串,那么(position()= last())如果还有一个不匹配的子字符串,则返回false。
由于您对不匹配的子字符串不感兴趣,更好的解决方案是使用tokenize():
<xsl:template match="value">
<xhtml:p>
<xsl:for-each select="tokenize(., '\p{{Nd}}\s\p{{Lu}}\s\p{{Nd}}', 'i')">
<xsl:if test="position() ne 1"><xhtml:br/></xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xhtml:p>
</xsl:template>
另请注意我对您的代码所做的其他一些风格改进:
我也倾向于避免使用“我”。正则表达式中的标志;而是将\p{Lu}
替换为更大的类别。
答案 1 :(得分:1)
试
<xsl:if test="position()!=last()">
代替