使用XSLT标记文本匹配正则表达式?

时间:2015-02-06 21:25:46

标签: xml xslt unicode xslt-2.0 saxon

我正在尝试在HTML文档上使用XSLT 2.0(Saxon-PE 9.6)来创建围绕指定的非拉丁语Unicode块(允许的空格)的所有连续字符行的标记。我需要将此过程应用于文档中的每个text()节点。我使用<xsl:analyze-string>和使用fn:replace()的两种方法取得了一些进展,但我还没有达成令人满意的完整解决方案。

例如,这里有一些包含印地语的文字:

输入:<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 + 097F。)

<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标签,但在正面,印地语的每个区域实际上都是被发现和处理的。我无法用span标签替换xxx代码,因为这是无效的XSLT。

3 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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分支只返回未修改的“普通”文本子字符串(您返回整个文本!)

答案 2 :(得分:1)

补充以前的答案,您可能需要注意的是,您可以用\p{IsDevanagari}代替[&#x0900;-&#x097f;]

相关问题