2015-02-06 48 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;]