2015-11-04 60 views
0

fiddledXSLT 2.0:限制一个<分析字符串>

我把链接到主文本的词汇表。

这里是一个身份模板变换:

<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,解决方案非常简单。但目前它躲过了我。

UPDATE:这似乎是工作(我还没有对所有使用情况虽然测试(类似于蒂姆·C的)

<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> 

UPDATE:我用迈克尔·凯的建议,并简化这是通过两遍和一遍来完成的。多遍是非常正确的选择,因为正则表达式变得非常复杂。为了防止术语链接被插入到不适当的地方,必须使用i标志来启用Java语言,然后用了很多预见's。后视会有帮助,但我无法弄清楚如何让它们工作。正则表达式语法中的<似乎会让事情发生。

回答

0

另一种方法是将当前正在做的beat的所有事件标记出来,然后在第二遍中删除不需要的事件。

+0

哦,那可能是票。使用简单模板进行两次传递,而不是使用复杂模板进行一次传递,对其具有吸引力。 – Paulb

0

你可以添加一个条件,你的模板匹配,仅匹配p没有前面的p,你的表达式匹配的元素:

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

模板的身体能保持在这个相同案件。

或者,你可以把支票模板的身体,就像这样:

<xsl:template match="page/p/text()"> 
    <xsl:variable name="p" select=".." /> 
    <xsl:analyze-string select="." regex="\s(beat)\s" flags="i"> 
     <xsl:matching-substring> 
      <xsl:choose> 
       <xsl:when test="$p/preceding-sibling::p[matches(text(), '\sbeat\s')]"> 
        <xsl:value-of select="."/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:text> </xsl:text> 
        <term keyref="beat"> 
         <xsl:value-of select="regex-group(1)"/> 
        </term> 
        <xsl:text> </xsl:text>         
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:matching-substring>    
     <xsl:non-matching-substring> 
      <xsl:value-of select="."/> 
     </xsl:non-matching-substring>    
    </xsl:analyze-string> 
</xsl:template> 
0

我想一个办法是用matches功能键text()节点,那么只有你的模板应用到首先在每一页中发现text(),都在XSLT 1.0 Muenchian分组的所采取的方法,只是在XSLT 2.0我们可以使用is操作者,我们可以限制key调用(在page的)一个子树:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 

    <xsl:output 
     method="xml" 
     omit-xml-declaration="no" 
     encoding="UTF-8" 
     indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="ref-on-page" match="page/p/text()" use="matches(., '\sbeat\s', 'i')"/> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- 
     putting links to glossary terms in text 
     how to make this hit on only the first occurrence on the page? 
    --> 

    <xsl:template match="page/p/text()[. is key('ref-on-page', true(), ancestor::page)[1]]"> 
     <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> 

</xsl:stylesheet> 
+0

我走向另一个方向。但我很感谢你的回答。我认为我没有充分利用“关键”,应该更频繁地使用它。我知道我使用过的几次,它大大提高了性能。 – Paulb

相关问题