是否可以从 xsl:analyze-string 中的重复正则表达式组中捕获值?

wst*_*wst 3 regex xslt

我想做这样的事情:

<xsl:analyze-string select="'ABCD'" regex="(A|B|C|D)+">
  <xsl:matching-substring>
     <xsl:for-each select="regex-group(1)">
         <letter><xsl:value-of select="." /></letter>
     </xsl:for-each>                    
  </xsl:matching-substring>
</xsl:analyze-string>
Run Code Online (Sandbox Code Playgroud)

=>

<letter>A</letter>
<letter>B</letter>
<letter>C</letter>
<letter>D</letter>
Run Code Online (Sandbox Code Playgroud)

但这似乎不可能,因为xsl:analyze-string只保留组中捕获的最后一个值,因此实际输出只是:

<letter>D</letter>    
Run Code Online (Sandbox Code Playgroud)

一般问题是处理可能以未知顺序出现的已知值。

wst*_*wst 5

xsl:analyze-string将在一个字符串中自动重复和匹配多次。如果您重写表达式以匹配子字符串 - 而不是使用锚点和/或显式重复组一次匹配整个字符串 - 您可以获得正确的输出:

<xsl:analyze-string select="'ABCD'" regex="(A|B|C|D)">
  <xsl:matching-substring>
   <letter><xsl:value-of select="regex-group(1)" /></letter>
  </xsl:matching-substring>
</xsl:analyze-string>
Run Code Online (Sandbox Code Playgroud)

=>

<letter>A</letter>
<letter>B</letter>
<letter>C</letter>
<letter>D</letter>
Run Code Online (Sandbox Code Playgroud)

但是,如果表达式的某些部分是严格排序的,而有些则不是,这会变得更加复杂。例如,假设有两个无序组本身是有序的:

(1|2|3|4)+(A|B|C|D)+
Run Code Online (Sandbox Code Playgroud)

重写这个正则表达式(1|2|3|4)|(A|B|C|D)仍然可以得到(用作输入21CB)的结果:

<number>2</number>
<number>1</number>
<letter>C</letter>
<letter>B</letter>
Run Code Online (Sandbox Code Playgroud)

但是重写的正则表达式也会匹配AB121A3C等,这些都不匹配原始表达式。如果有人对此有更好的解决方案,我会非常感兴趣。理想的解决方案是保留重复组的先前捕获,例如在 .NET 中。

  • 不幸的是 xsl:analyze-string 只会捕获最后一个匹配项。这是因为它被设计为可以使用广泛可用的正则表达式引擎来实现,并且许多正则表达式引擎都有这个限制。 (3认同)