2015-02-06 49 views
3

我試圖在HTML文檔上使用XSLT 2.0(Saxon-PE 9.6)來創建標記,該標記圍繞指定的非拉丁Unicode塊(允許空格)中的所有連續字符運行。我需要將此過程應用於文檔中的每個文本()節點。使用<xsl:analyze-string>和使用fn:replace()的兩種方法取得了一些進展,但我無法獲得令人滿意的完整解決方案。使用XSLT標記文本匹配正則表達式?

例如,這裏是一個包含印地文一些文字:

輸入:<p>चाय का कप means ‘cup of tea’ in हिन्दि.</p>

所需的輸出:<p><span xml:lang="hi-Deva">चाय का कप</span> means ‘cup of tea’ in <span xml:lang="hi-Deva">हिन्दि</span>.</p>

怎麼能這個過程在XSLT 2.0中實現?


這裏是我的嘗試與<xsl:analyze-string>

(注:印地文語言使用梵文代碼塊U +每日0900時至U +撒馬利亞語。)

<xsl:template match="text()"> 
    <xsl:variable name="textValue" select="."/> 

    <xsl:analyze-string select="$textValue" regex="(\s*.*?)([&#x0900;-&#x097f;]+)((\s+[&#x0900;-&#x097f;]+)*)(\s*.*)"> 

    <xsl:matching-substring> 
     <xsl:value-of select="regex-group(1)"/> 
     <span xml:lang="hi-Deva"><xsl:value-of select="regex-group(2)"/><xsl:value-of select="regex-group(3)"/></span> 
     <xsl:value-of select="regex-group(5)"/> 
    </xsl:matching-substring> 

    <xsl:non-matching-substring> 
     <xsl:value-of select="$textValue"/> 
    </xsl:non-matching-substring> 

    </xsl:analyze-string> 
</xsl:template> 

在測試輸入,這產生: <p><span xml:lang="hi-Deva">चाय का कप</span> means ‘cup of tea’ in हिन्दि.</p>這種方法錯過了印地文文本的第二個區域(हिन्दि)。我需要一種方法來查找和標記正則表達式匹配的所有匹配項。

我的第二種方法使用fn:replace()

<xsl:template match="text()"> 
    <xsl:value-of select='fn:replace(., "[&#x0900;-&#x097f;]+(\s+[&#x0900;-&#x097f;]+)*", "xxx$0xxx")'/> 
</xsl:template> 

在測試輸入這將產生:<p>xxxचाय का कपxxx means ‘cup of tea’ in xxxहिन्दिxxx.</p>這顯然是不正確的,因爲在印地文被包裹在XXX的,不能跨越的標籤,但積極的一面,每個區域的印地語實際上是被發現和處理的。我無法用span標記替換xxx代碼,因爲這是無效的XSLT。

+0

您在第一個(分析字符串)方法中使用的正則表達式一次匹配_entire_輸入字符串,所以您只需獲取墊子清楚的子字符串塊發射一次。相反,你需要一個只匹配一個印地語段的正則表達式,那麼匹配子字符串將針對印地語引發,非匹配子字符串針對非印地語段引發。 – 2015-02-06 21:57:11

+0

關於第一個正則表達式,我在我的搜索中找到的所有xsl:analyze-string示例與整條線匹配。我也沒有找到描述其多個匹配行爲的文檔。在我的xsl:analyze-string實驗中,我以爲我嘗試了以下解決方案中使用的確切正則表達式,但顯然我做了一些其他錯誤,導致結果模糊不清。 – keithm 2015-02-06 22:39:12

+0

我在spec中找到了確切的語言http://www.w3.org/TR/xslt20/#element-analyze-string:「找到第一個匹配項後,指令繼續通過重複搜索,從第一個角色開始,不包含在前一場比賽中。「 – keithm 2015-02-07 10:45:10

回答

5

我想出了http://xsltransform.net/jyH9rMo這只是做

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

    <xsl:template match="/"> 
     <hmtl> 
     <head> 
      <title>New Version!</title> 
     </head> 
     <xsl:apply-templates/> 
     </hmtl> 
    </xsl:template> 

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

    <xsl:template match="text()"> 
    <xsl:analyze-string select="." regex="([&#x0900;-&#x097f;]+)((\s+[&#x0900;-&#x097f;]+)*)"> 

    <xsl:matching-substring> 
     <span xml:lang="hi-Deva"><xsl:value-of select="."/></span> 
    </xsl:matching-substring> 

    <xsl:non-matching-substring> 
     <xsl:value-of select="."/> 
    </xsl:non-matching-substring> 

    </xsl:analyze-string>  
    </xsl:template> 
</xsl:transform> 
+0

由於在中使用了的完整解決方案而被接受的答案。 – keithm 2015-02-06 22:15:58

1

這應該工作(代碼後的一些評論):

XSLT 2.0

<xsl:analyze-string select="$textValue" regex="([&#x0900;-&#x097f;]+)((\s+[&#x0900;-&#x097f;]+)*)"> 
    <xsl:matching-substring> 
      <span xml:lang="hi-Deva"><xsl:value-of select="regex-group(1)"/><xsl:value-of select="regex-group(2)"/></span> 
    </xsl:matching-substring> 
    <xsl:non-matching-substring> 
      <xsl:value-of select="."/> 
    </xsl:non-matching-substring> 
</xsl:analyze-string> 
  • 的正則表達式是從你的第二次嘗試的一個(因爲它是正確的匹配只有印地文文本片段!),只是第一部分圍繞括號
  • matching-substring分支將span圍繞印地文文本
  • non-matching-substring分支剛剛返回未修改的「正常」的文本串(你正在返回整個文本!)
1

補充了以前的答案,你可能會注意到,您可以使用\p{IsDevanagari}代替[&#x0900;-&#x097f;]