XSLT 2.0:限制<analyze-string>

时间:2015-11-04 12:51:48

标签: xslt

fiddled

我在主要文本中添加了词汇表的链接。

以下是身份转换中的模板:

<xsl:template match="page/p/text()">
    <xsl:analyze-string select="." regex="\s(beat)\s" flags="i">
        <xsl:matching-substring>
            <xsl:text> </xsl:text>
            <term keyref="beat">
                <xsl:value-of select="regex-group(1)"/>
            </term>
            <xsl:text> </xsl:text>                                
        </xsl:matching-substring>            
        <xsl:non-matching-substring>
            <xsl:value-of select="."/>
        </xsl:non-matching-substring>            
    </xsl:analyze-string>
</xsl:template>

以下是不需要的结果:

<page>
 <p>1. Using a whip, <term keyref="beat">beat</term> egg whites..</p>
 <p>2. Add sugar; <term keyref="beat">beat</term> on medium.</p>
 <p>3. <term keyref="beat">Beat</term> at high speed until..</p>
</page>

理想情况下,您只需要页面上第一次出现该字词的链接(本例中的第1行)。

我所有解决这个问题的尝试都是复杂而不成功的。通常使用XSLT,解决方案是非常简单的代码。但它现在就躲避了我。

更新:这似乎有效(我还没有针对所有用例进行测试。(类似于Tim C&#39;)

<xsl:template match="page/p/text()">
    <xsl:choose>
        <!-- 
            count how times the word has occurred up to now,
            if 0 times, wrap it in <term> 
        -->
        <xsl:when test="count(tokenize(preceding::*[1]/text(), 'beat')) = 0">
            <xsl:analyze-string select="." regex="\s(beat)\s" flags="i">
                <xsl:matching-substring>
                    <xsl:text> </xsl:text>
                    <term keref="beat">
                        <xsl:value-of select="regex-group(1)"/>
                    </term>
                    <xsl:text> </xsl:text>                                
                </xsl:matching-substring>            
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>            
            </xsl:analyze-string>
        </xsl:when>
        <!-- the word previously occurred; leave it as is -->
        <xsl:otherwise>
            <xsl:copy-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

更新:我使用了Michael Kay的建议,并通过两次传递而不是一次来简化了这一点。由于正则表达式变得非常复杂,因此多传递成为正确的选择。为防止词汇表链接插入不适当的位置,必须使用i标志启用java方言,然后使用许多预见。看起来很有帮助,但我无法弄清楚如何让它们发挥作用。正则表达式语法中的<似乎可以解决问题。

3 个答案:

答案 0 :(得分:0)

您可以为模板匹配添加条件,以便仅匹配不具有与您的表达式匹配的前p的{​​{1}}元素:

p

在这种情况下,模板的主体可以保持不变。

或者,您可以将检查放在模板的正文中,如下所示:

<xsl:template match="page/p[not(preceding-sibling::p[matches(text(), '\sbeat\s')])]/text()">

答案 1 :(得分:0)

我认为一种方法是使用perl -ane 'print if $F[0] == $F[1]' file 函数键入text()节点,然后仅将模板应用于每个页面中找到的第一个matches,就像在XSLT中采用的方法一样1.0使用Muenchian分组,只有在XSLT 2.0中我们可以使用text()运算符,我们可以将is调用限制为子树(key):

page

答案 2 :(得分:0)

另一种方法是标记当前正在执行的所有beat,然后在第二次传递中删除不需要的事件。