【问题标题】:Can't get the "s" flag to work in regex in Saxon 9.5无法在撒克逊 9.5 的正则表达式中使用“s”标志
【发布时间】:2014-10-01 04:37:43
【问题描述】:

我有一个这样的 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 中都可以正常工作。但是,我现在还需要删除部分有效负载,特别是一个元素,包括标签及其所有内容(之间的所有文本)。

由于在原始 XML 文件中,有效负载只是一个字符串,因此我使用 replace() 和一个匹配不需要的元素的正则表达式和空字符串作为替换字符串。我包括“s”标志,以获得“。”在正则表达式中匹配不需要的元素中存在的换行符。因此,容器信封元素的模板更改为:

  <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 命令行窗口变得混乱:

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

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

仅当我使用“s”标志时才会出现问题。但如果我放弃它,我将无法获得比赛。我尝试了一种不需要标志的替代方法并且做同样的事情:

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

但是我在撒克逊语上遇到了同样的错误。再一次,Altova 做对了。我不确定问题是否出在我的代码上,因为它在 Altova 中运行良好。但我真的很想让这个在撒克逊也能发挥作用。那么,怎么了?

【问题讨论】:

  • 杂乱无章的消息通常是堆栈跟踪,可帮助确定 Java 应用程序的确切故障位置,因此请考虑提供完整的堆栈跟踪。最好提供最少但完整的 XML 和 XSLT 示例,以便重现错误。最快的解决方案也是在撒克逊邮件列表或支持论坛上发布。
  • @Martin:就我所见,完整堆栈跟踪的问题在于它不断重复。它总是上面两行的交替。没有其他的。因此,如果我复制了数十行相同的行,那将无济于事。此外,它跨越了保留在 DOS 命令行窗口中的行缓存。因此,我最初对转换的调用以及重复消息的初始行都丢失了。如果我一直向上滚动窗口,我唯一能看到的就是那两行错误消息。
  • 我很乐意提供我正在使用的完整 XML 的示例。没有在这里做,因为它对于这个场地来说太大了。这是合适的地方吗:lists.sourceforge.net/lists/listinfo/saxon-help
  • 如果您想向 saxonica 提出支持查询,首选途径是 http;//saxonica.plan.io。

标签: xslt saxon


【解决方案1】:

由于 Saxon 9.6 现已推出,甚至 Home Edition 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,然后使用模板过滤掉您不需要的任何元素。

【讨论】:

  • 马丁,你的方法是迄今为止最好的方法。首先,它更高效(对处理器没有回溯压力)。其次,它使我不必使用 XML 管道。现在,已解析的 XML 可随时用于任何进一步的处理。 SaxonHE 9.6 支持 XPath 3.0 函数是个好消息。这使得处理嵌套的 XML 有效负载变得更加容易。感谢您的慷慨建议!
【解决方案2】:

您在 Saxon 正则表达式引擎中遇到堆栈溢出,因为回溯太多。我们在未来的 9.6 版本中对此进行了修复,但与此同时,您需要小心执行过多回溯的正则表达式。

真的,你的方法是错误的。不应该使用正则表达式来解析 XML。你的表达是错误的,因为它可以匹配它不应该匹配的东西,例如评论中看起来像结束标签的东西。您无法通过调整正则表达式来正确处理它,因为 XML 具有递归语法,而正则表达式无法处理递归语法。 Saxon 为此提供了 parse-xml()。

【讨论】:

  • 迈克尔,我完全同意你的看法。最好的方法是使用 fn:parse-xml() 或 saxon:parse() 解析有效负载。但是,SaxonHE 中既不提供 XSLT 3.0 特性,也不提供扩展功能。所以,我只剩下原始的正则表达式替代方案。这导致我的堆栈溢出(非常恰当:))。无论如何,很高兴知道 Saxon 9.6 将解决回溯问题(我可以知道什么时候吗?)。在 Saxon 中构建更强大的正则表达式引擎并没有什么坏处。感谢您的反馈!
猜你喜欢
  • 2016-01-25
  • 2015-06-09
  • 1970-01-01
  • 2019-01-12
  • 2018-07-17
  • 2013-03-15
  • 2020-02-08
  • 2011-06-21
  • 2010-10-02
相关资源
最近更新 更多