2012-03-11 144 views
3

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

时使用以下为“血压”搜索,返回与“造血”,“压力”和“血压”的所有节点。

我只希望返回包含“血压”的节点。使用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> 

回答

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"字紧随其后。


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文档(上文)施加相同correst结果产生

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

说明

  1. 转换为小写。

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

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

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

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

+0

伟大的回应Dimitre,谢谢。通过我的代码后,我实际上产生了正确的结果。我使用的表单发布数据,我认为是造成这个问题。再次感谢 – rossjha 2012-03-13 10:01:21

0

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

+0

感谢Martin,你知道任何其他方式来返回我使用XSLT后的结果吗? – rossjha 2012-03-11 15:29:02

0

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

正则表达式由该指令所使用的,和控制这些正则表达式的解释标志,必须符合 [函数和操作]中定义的语法(见Section 7.6.1 Regular Expression Syntax ),其是本身基于在 [XML Schema Part 2]定义的语法。

第一个链接来自报价显示我们没有\b的存在。

同为第二链路Single Character Escape

但是,如果我们最后的文档中滚动了一下,我们可以发现字符类(Category Escape)。为了达到类似的效果[\p{P}\p{Z}]:与使用相结合的punctuationspace类。

+0

感谢您的信息,可以在LAMP环境中使用XSLT 2.0吗? – rossjha 2012-03-11 15:45:57

+0

咋,但不是直接。例如:http://stackoverflow.com/questions/2085632/will-xpath-2-0-and-or-xslt-2-0-be-implemented-in-php – kirilloid 2012-03-11 16:08:40

+0

@rossjha:不,AFAIK,除非你安装一个XSLT 2.0处理器,如基于Java的Saxon 9.x.查看我对* * XSLT 1.0和XSLT 2.0解决方案的回答。 :) – 2012-03-11 16:27:04