XSLT 2.0正则表达式问题(不同匹配时打开和关闭元素)

时间:2010-06-26 12:51:18

标签: regex xslt text-processing xslt-2.0

我在某种程度上简化了问题,但我希望我仍然抓住了问题的本质。

假设我有以下简单的XML文件:

<main>
  outside1
  ===BEGIN===
    inside1
  ====END====
  outside2
  =BEGIN=
    inside2
  ==END==
  outside3
</main>

然后我可以使用以下XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:template match="text()">

  <xsl:analyze-string select="." regex="=+BEGIN=+">
     <xsl:matching-substring>
        <section/>
     </xsl:matching-substring>
     <xsl:non-matching-substring>
          <xsl:analyze-string select="." regex="=+END=+">  
             <xsl:matching-substring>
                <_section/>
             </xsl:matching-substring>
             <xsl:non-matching-substring>
                <xsl:value-of select="."/>
             </xsl:non-matching-substring>
          </xsl:analyze-string>
     </xsl:non-matching-substring>
  </xsl:analyze-string>

</xsl:template>

</xsl:stylesheet>

将其转换为以下内容:

<?xml version="1.0" encoding="UTF-8"?>
  outside1
  <section/>
    inside1
  <_section/>
  outside2
  <section/>
    inside2
  <_section/>
  outside3

以下是问题:

多个正则表达式

是否有更好的方法来匹配两个不同的正则表达式,而不是像上面所做的那样将它们嵌套在另一个中?

  • 如果它们不容易像这样嵌套怎么办?
  • 我可以在text()中使用XSL模板匹配和转换正则表达式匹配吗?
    • 在这种情况下,我有两个模板,每个模板对应一个正则表达式
    • 如果可能,这将是理想的解决方案

正则表达式上的打开和关闭元素匹配

显然,而不是:

<section/>
   inside
<_section/>

我最终真正想要的是:

<section>
   inside
</section>

那你怎么做?我不确定是否有可能在一个正则表达式匹配中打开一个元素并在另一个正则表达式中关闭它(即如果没有匹配的那个怎么办?结果将不是格式良好的XML!),但它看起来像这项任务非常典型,必须为他们提供惯用的解决方案。

注意:我们可以假设部分不会重叠,因此也不会嵌套。我们也可以假设它们总是以正确的对出现。


其他信息

所以基本上我正在尝试完成Perl中的所有内容:

s/=+BEGIN=+/<section>/
s/=+END=+/<\/section>/

我正在寻找一种在XSLT中执行此操作的方法,因为:

  • 关于正则表达式匹配的上下文,它会更强大
    • (即它应该只转换text()个节点)
  • 在匹配各种XML实体方面也更加健壮

1 个答案:

答案 0 :(得分:1)

此转化

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs"
>
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="text()">
   <xsl:analyze-string select="." flags="mx"
    regex="=+BEGIN=+((.|\n)*?)=+END=+">

   <xsl:matching-substring>
    <section><xsl:value-of select="regex-group(1)"/></section>
   </xsl:matching-substring>

   <xsl:non-matching-substring>
    <xsl:value-of select="."/>
   </xsl:non-matching-substring>
 </xsl:analyze-string>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<main>
  outside1
  ===BEGIN===
    inside1
  ====END====
  outside2
  =BEGIN=
    inside2
  ==END==
  outside3
</main>

产生想要的结果

<main>
  outside1
  <section>
    inside1
  </section>
  outside2
  <section>
    inside2
  </section>
  outside3
</main>