Xslt Can';我得不到;s";在Saxon 9.5中使用正则表达式的标志

Xslt Can';我得不到;s";在Saxon 9.5中使用正则表达式的标志,xslt,saxon,Xslt,Saxon,我有一个XML信封/有效负载结构,如下所示: <RootEnvelopeTag> <EnvelopeTag /> <EnvelopeTag /> <EnvelopeTagContainingPayload> &lt;WantedPayloadTag&gt;Some text and nested tags.&lt;/WantedPayloadTag&gt;&lt;Unw

我有一个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>

WantedPayloadTag部分文本和嵌套标记。/WantedPayloadTagUnwantedPayloadTag大量文本和嵌套标记。/UnwantedPayloadTag
为了提取有效负载,通过删除所有信封元素,我使用以下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中运行良好。但我真的很想让这个在萨克森也能用。那么,怎么了?

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


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

<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,然后使用模板筛选出任何您不想要的元素。

消息的混乱通常是堆栈跟踪,帮助识别java应用程序在哪里失败,因此考虑提供完整的堆栈跟踪。最好提供最小但完整的XML和XSLT示例,以便重现错误。最快的解决方法也是在Saxon邮件列表或支持论坛上发布。@Martin:就我所见,完整堆栈跟踪的问题是它不断重复。它总是上面两行的交替。没有别的了。所以,如果我复制了几十行同样的内容,也不会有多大帮助。此外,它跨越了DOS命令行窗口中保留的缓存行。因此,我最初对转换的调用以及重复消息的初始行都丢失了。如果我一直向上滚动窗口,唯一能看到的就是那两行错误消息。我很乐意提供我正在使用的完整XML的示例。我没有在这里做,因为这个场地太大了。这是合适的地方吗:?如果你想用saxonica提出支持查询,首选的路由是http//saxonica,plan,io,我非常同意你,Michael。最好的方法是使用fn:parse-xml()或saxon:parse()解析有效负载。但是,SaxonHE中既没有XSLT 3.0特性,也没有扩展函数。所以,我只剩下了原始正则表达式的选择。这导致我的堆栈溢出(非常恰当:)。无论如何,很高兴知道Saxon9.6将解决回溯问题(我可以知道什么时候吗?)。在萨克森内置更强大的正则表达式引擎并没有什么坏处。谢谢你的反馈!马丁,你的方法是最好的。首先,它更高效(处理器上没有回溯压力)。其次,它使我不必使用XML管道。现在,解析后的XML可随时用于任何进一步的处理。SaxonHE9.6支持XPath3.0函数,这是一个好消息。这使得处理嵌套XMLs有效负载更容易。谢谢你慷慨的建议!