XSLT使用正则表达式,字边界搜索XML

时间:2012-03-11 15:08:01

标签: php xml xslt

是否可以使用正则表达式使用XSLT搜索XML内容?我可以使用包搜索节点,但是我需要使用单词边界(例如/\bmy phrase\b/i)来搜索短语而不仅仅是单个单词。

使用以下方法搜索“血压”时,将返回所有“血液”,“压力”和“血压”的节点。

我只想要返回包含'血压'的节点。使用PHP preg_match,我可以使用:/\b$keywords\b/i

实现此目的
<xsl:template match="//item">
    <xsl:choose>
        <xsl:when test="contains(translate(title, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), $keyword) or contains(translate(content, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), $keyword)">
            <item>
                <title><xsl:value-of select="title"/></title>
                <content><xsl:value-of select="content"/></content>
                <date><xsl:value-of select="date"/></date>
                <author><xsl:value-of select="author"/></author>
            </item>
        </xsl:when>
    </xsl:choose>
</xsl:template>

3 个答案:

答案 0 :(得分:2)

<强>予。您可以在XSLT 2.0中执行类似的操作:

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

 <xsl:template match="s">
  <xsl:variable name="vWords" select=
  "tokenize(lower-case(string(.)),
            '[\s.?!,;—:\-]+'
            ) [.]
  "/>
  <xsl:sequence select=
   " for $current in .,
         $i in 1 to count($vWords)
     return
        if($vWords[$i] eq 'blood'
          and
           $vWords[$i+1] eq 'pressure'
           )
           then .
           else ()
  "/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

将此XSLT 2.0转换应用于以下XML文档(问题中未提供此类文档!!!):

<t>
 <s>He has high blood pressure.</s>
 <s>He has high Blood Pressure.</s>
 <s>He has high Blood
 Pressure.</s>

  <s>He was  coldblood Pressured.</s>

</t>

想要的,正确的结果(只有包含“血”和“压力”的元素(不区分大小写且作为两个相邻的单词)生成

<s>He has high blood pressure.</s>
<s>He has high Blood Pressure.</s>
<s>He has high Blood
 Pressure.</s>

<强>解释

  1. 使用tokenize()函数拆分nn个字母的字符串,使用不区分大小写和多行模式的标志。

  2. 迭代tokenize()的结果,找到一个"blood"字后紧跟"pressure"字。


  3. <强> II。 XSLT 1.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="vUpper" select=
     "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    
     <xsl:variable name="vLower" select=
     "'abcdefghijklmnopqrstuvwxyz'"/>
    
     <xsl:variable name="vSpaaaceeees" select=
     "'                                                                               '
     "/>
    
     <xsl:variable name="vAlpha" select="concat($vLower, $vUpper)"/>
    
     <xsl:template match="s">
       <xsl:variable name="vallLower" select="translate(., $vUpper, $vLower)"/>
         <xsl:copy-of select=
         "self::*
           [contains
            (concat
             (' ',
              normalize-space
               (translate($vallLower, translate($vallLower, $vAlpha, ''), $vSpaaaceeees)),
              ' '
              ),
    
             ' blood pressure '
             )
           ]
      "/>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    当此转换应用于同一XML文档(上图)时,会产生相同的最终结果

    <s>He has high blood pressure.</s>
    <s>He has high Blood Pressure.</s>
    <s>He has high Blood
     Pressure.</s>
    

    <强>解释

    1. 转换为小写。

    2. 使用双翻译方法将任何非字母字符替换为空格。

    3. 然后使用normalize-space()用一个空格替换任何一组相邻的空格。

    4. 然后用空格包围这个结果。

    5. 最后,验证当前结果是否包含字符串" blood pressure "

答案 1 :(得分:0)

XSLT和XPath 2.0确实有一个支持正则表达式的匹配函数,XSLT和XPath 1.0没有这样的功能,你需要使用你的XSLT处理器支持的扩展函数:http://www.exslt.org/regexp/functions/match/index.html。 但是,即使使用XSLT / XPath 2.0,我认为支持的正则表达式语言也不支持任何“单词边界”模式。

答案 2 :(得分:0)

http://www.w3.org/TR/xslt20/#regular-expressions

  

此指令使用的正则表达式以及控制这些正则表达式解释的标志必须符合 [Functions and Operators]中定义的语法(请参阅Section 7.6.1 Regular Expression Syntax),它本身基于 [XML Schema Part 2]中定义的语法。

第一个链接引用显示我们没有\b

第二个链接Single Character Escape

相同

但是如果我们稍微滚动一下最后一个文档,我们就可以找到字符类(Category Escape)。并使用punctuationspace类的组合:[\p{P}\p{Z}]以达到类似的效果。