2012-03-11 76 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