在Saxon 9.5中无法获得正则表达式的“s”标志

时间:2014-10-01 04:37:44

标签: xslt saxon

我有一个像这样的XML信封/有效负载结构:

<RootEnvelopeTag>
    <EnvelopeTag />
    <EnvelopeTag />
    <EnvelopeTagContainingPayload>
        &lt;WantedPayloadTag&gt;Some text and nested tags.&lt;/WantedPayloadTag&gt;&lt;UnwantedPayloadTag&gt;Lots of text and nested tags.&lt;/UnwantedPayloadTag&gt;
    </EnvelopeTagContainingPayload>
</RootEnvelopeTag>

要通过删除所有信封元素来提取有效负载,我使用以下XSLT:

<xsl:transform 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 method="text" encoding="utf-8"/>
  <xsl:template match="/">
    <xsl:apply-templates select="*/EnvelopeTagContainingPayload"/>
  </xsl:template>
  <xsl:template match="EnvelopeTagContainingPayload">
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:transform>

结果是一个新的文本文件,一旦解析为XML,就允许我只使用有效负载XML。

这在Saxon HE 9.5和AltovaXML 2013中均可正常工作。但是,我现在还需要删除部分有效负载,特别是一个元素,包括标签及其所有内容(&lt; UnwantedPayloadTag&gt; ; ALLWXT IN BETWEEN&lt; / UnwantedPayloadTag&gt;)。

因为在原始XML文件中,有效负载只是一个字符串,所以我使用带有与不需要的元素匹配的正则表达式的replace()和作为替换字符串的空字符串。我包括&#34; s&#34;旗帜,以获得&#34;。&#34;在正则表达式中匹配不需要的元素中存在的换行符。因此,容器包络元素的模板更改为:

  <xsl:template match="EnvelopeTagContainingPayload">
    <xsl:variable name="removeUnwanted" as="xs:string" select="replace(., '&lt;UnwantedPayloadTag.*UnwantedPayloadTag&gt;', '', 's')" />
    <xsl:value-of select="$removeUnwanted"/>
  </xsl:template>

在AltovaXML中,这可以无缝地工作。结果与预期完全一致。但在撒克逊人中,它造成了严重破坏。没有输出;相反,我在命令行中无休止地重复以下错误消息,使整个DOS命令行窗口混乱:

at net.sf.saxon.regex.Operation $ OpStar.exec(Operation.java:235)

at net.sf.saxon.regex.REMatcher.matchNodes(REMatcher.java:413)

问题仅在我使用&#34; s&#34;旗。但如果我放弃它,我就不会得到这场比赛。我尝试了一种不需要旗帜的替代方案并做同样的事情:

    <xsl:variable name="removeUnwanted" as="xs:string" select="replace(., '&lt;UnwantedPayloadTag[\s\S]*UnwantedPayloadTag&gt;', '')" />

但我在撒克逊人身上得到同样的错误。而且,Altova再次做对了。我不确定问题是否在我的代码上,因为它在Altova中工作正常。但我真的希望这也能在萨克森工作。那么,有什么不对?

2 个答案:

答案 0 :(得分:1)

您在Saxon正则表达式引擎中遇到堆栈溢出,因为回溯过多。我们在将来的9.6版本中已经解决了这个问题,但在此期间你需要注意那些做太多回溯的正则表达式。

真的,你的做法是错误的。不应使用正则表达式来解析XML。你的表达是错误的,因为它可以匹配它不应该匹配的东西,例如:注释中的某些内容看起来像结束标记。你无法通过调整正则表达式来解决问题,因为XML具有递归语法,而正则表达式无法处理递归语法。 Saxon为此提供了parse-xml()。

答案 1 :(得分:1)

由于Saxon 9.6现已推出,即使家庭版HE支持XPath 3.0等功能,例如parse-xml-fragment,现在正在解决问题的正确方法

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">

  <xsl:output method="xml" encoding="utf-8"/>

  <xsl:template match="/">
    <xsl:apply-templates select="*/EnvelopeTagContainingPayload"/>
  </xsl:template>

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

  <xsl:template match="EnvelopeTagContainingPayload">
    <xsl:apply-templates select="parse-xml-fragment(.)"/>
  </xsl:template>

  <xsl:template match="UnwantedPayloadTag"/>

</xsl:transform>

通过这种方式,您只需将标记解析为XML,然后使用模板过滤掉您不想要的任何元素。