使用查找标记单词,最好的方法是什么?

时间:2013-05-17 19:52:06

标签: xslt-2.0

我有一些我想测试的字符串,看它们是否包含特定的单词。有问题的单词位于查找节点中,如果匹配,则需要标记字符串中的单词。我有一个几乎可以正常使用的脚本,但我想知道我是否使用最佳格式,因为我认为它相当耗费资源,而且不是非常万无一失。

示例xml:

<Main>
<NTUS>
    <NTU>match</NTU>
    <NTU>test</NTU>
</NTUS>
<Folder id="update">
    <about>This content is not in a span so we ignore it completely, even if we would have a match</about>
    <Title>
        <span class="string simple" lang="en">Some test content containing a single match</span>
    </Title>
    <Content>
        <span class="string complex" lang="en">Also keywords in sub elements should <strong>pass the test</strong>, and match.</span>
    </Content>
</Folder>
</Main>

我当前的xslt:

    <xsl:param name="units">
    <xsl:copy-of select="//NTU"/>
</xsl:param>
<xsl:template match="/">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="NTUS"/>

<xsl:template match="text()[ancestor::span]">
    <xsl:analyze-string select="." regex="\s+">
        <xsl:matching-substring>
            <xsl:value-of select="."/>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <xsl:variable name="theWord" select="."/>
            <xsl:choose>
                <xsl:when test="$units/*[text()=$theWord]">
                    <ntu>
                        <xsl:value-of select="."/>
                    </ntu>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:template>

结果如下:

<Main>
<Folder id="update">
    <about>This content is not in a span so we ignore it completely, even if we would have a match</about>
    <Title>
        <span class="string simple" lang="en">Some <ntu>test</ntu> content containing a single <ntu>match</ntu></span>
    </Title>
    <Content>
        <span class="string complex" lang="en">Also keywords in sub elements should <strong>pass the <ntu>test</ntu></strong>, and match.</span>
    </Content>
</Folder>
</Main>

除了最后一个节点之外几乎没有问题,因为[match]位于句子的末尾,因此没有通过正则表达式。我可以调整它以使其匹配,但它可能变得相当复杂,所以我想知道是否有更好的方法来解决这个问题。

编辑:当你使用逗号分隔列表时似乎存在一个小的不当行为(可能在其他场合也是如此,但我注意到了这一点)......

例如跟随xml

<Main>
<NTUS>
    <NTU>OPTION1</NTU>
    <NTU>OPTION2</NTU>
    <NTU>OPTION3</NTU>
    <NTU>OPTION4</NTU>
    <NTU>OPTION5</NTU>
</NTUS>
<local xml:lang="en">
    <span>Test string containing some comma seperarated lookup values: OPTION1, OPTION2, OPTION3, OPTION4, OPTION5</span>
</local>

应用脚本时返回以下内容:

<span>Test string containing some comma seperarated lookup values: <ntu>OPTION1</ntu>, OPTION2, <ntu>OPTION3</ntu>, OPTION4, <ntu>OPTION5</ntu></span>

所以跳过每一秒的比赛。知道是什么导致了这种行为吗?

1 个答案:

答案 0 :(得分:0)

此转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vPatterns" select=
 "string-join(/*/NTUS/*, '|')"/>

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

 <xsl:template match="span//text()">
  <xsl:analyze-string select="." regex=
   "(^|(\P{{L}})+)({$vPatterns})($|(\P{{L}})+)">
    <xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
    <xsl:matching-substring>
      <xsl:value-of select="regex-group(1)"/>
      <ntu><xsl:value-of select="regex-group(3)"/></ntu>
      <xsl:value-of select="regex-group(4)"/>
    </xsl:matching-substring>
  </xsl:analyze-string>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档时:

<Main>
<NTUS>
    <NTU>match</NTU>
    <NTU>test</NTU>
</NTUS>
<Folder id="update">
    <about>This content is not in a span so we ignore it completely, even if we would have a match</about>
    <Title>
        <span class="string simple" lang="en">Some test content containing a single match</span>
    </Title>
    <Content>
        <span class="string complex" lang="en">Also keywords in sub elements should <strong>pass the test</strong>, and match.</span>
    </Content>
</Folder>
</Main>

产生了想要的正确结果:

<Main>
    <NTUS>
        <NTU>match</NTU>
        <NTU>test</NTU>
    </NTUS>
    <Folder id="update">
        <about>This content is not in a span so we ignore it completely, even if we would have a match</about>
        <Title>
            <span class="string simple" lang="en">Some <ntu>test</ntu> content containing a testmatch or a single <ntu>match</ntu></span>
        </Title>
        <Content>
            <span class="string complex" lang="en">Also keywords in sub elements should <strong>pass the <ntu>test</ntu></strong>, and <ntu>match</ntu>.</span>
        </Content>
    </Folder>
</Main>