0

我想从 XSLT 3 和 Saxon HE 10.6 的响应中过滤 XML 元素

<!-- https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE -->
<dependency>
    <groupId>net.sf.saxon</groupId>
    <artifactId>Saxon-HE</artifactId>
    <version>10.6</version>
</dependency>

我在https://xsltfiddle.liberty-development.net/3MP42Pchttps://xsltfiddle.liberty-development.net/3MP42Pc/1上保存了案例

我希望能够使用

<xsl:mode on-no-match="shallow-skip" />

(即:跳过与过滤器不匹配的元素。)

所以我想复制所有匹配一些更深的属性值的元素

该结构就像带有状态的鞋子数据集,看起来像账单上的通用项目。

账单.xml

  <bill>
    <item>
      <shoes>
        <status>0</status>
      </shoes>
    </item>
    <item>
      <shoes>
        <status>1</status>
      </shoes>
    </item>
    <item>
      <shoes>
        <status>2</status>
      </shoes>
    </item>
  </bill>

我想要 status=0 的通用物品(任何种类(鞋子))

(否则说:跳过 '*/[status=0'] 不匹配的项目)

票据.xslt

<xsl:stylesheet version="3.0">
  <xsl:mode on-no-match="shallow-skip" />
  <xsl:template match="item/*[status=0]"/>
</xsl:stylesheet>

结果必须是

<bill>
  <item>
    <shoes><status>0</status></shoes>
  </item>
</bill>

唉,这个脚本什么也没找到

但。如果是

<xsl:mode on-no-match="shallow-copy" />

它找到(如预期的那样)所有不是 status=0 的项目

<bill>
  <item/>
  <item>
    <shoes><status>1</status></shoes>
  </item>
  <item>
    <shoes><status>2</status></shoes>
  </item>
</bill>

如果我使用

<xsl:mode on-no-match="deep-copy" />

它找到所有项目(无过滤)。

对我来说这似乎不太合乎逻辑,即使 item 元素具有上下文。

我使用 SAXON HE 版本 10.6,与 javax.xml.transform 的代码的唯一区别是使用

TransformerFactory factory = new **BasicTransformerFactory**();

问题是如何制作一个优雅的小脚本来执行此操作:输出整个 xml,跳过不匹配的项目。

4

3 回答 3

0

我想你想用<xsl:mode on-no-match="shallow-copy"/>with <xsl:template match="item[not(*/status = 0)]"/>(或者<xsl:template match="item/*[not(status = 0)]"/>如果item元素都需要被复制,只有他们的孩子需要被过滤))。

除非<xsl:mode on-no-match="shallow-skip" />您明确添加<xsl:template match="item[*/status = 0]"><xsl:copy-of select="."/></xsl:template>. 即使那样你也会失去根元素。

如果您查看https://www.w3.org/TR/xslt-30/#built-in-templates-shallow-skip它会说:

使用指定模式处理树的效果是 on-no-match="shallow-skip"从结果文档中删除文本内容和标记,除非有明确的用户编写的模板规则另有规定。

于 2021-11-08T20:57:15.173 回答
0

谢谢马丁

所以逻辑更进一步。

显式写入节点的提示从根标记中丢失

https://xsltfiddle.liberty-development.net/3MP42Pc/2

所以解决方案是使用

<xsl:mode on-no-match="shallow-copy"/> 
<xsl:template match="item/*[not(status = 0)]"/>

https://xsltfiddle.liberty-development.net/3MP42Pc/3

迈克尔关于 on-no-match="shallow-skip" 的建议也适用,包括根标签,潜入后代。

<xsl:template match="*[descendant-or-self::status=0] | status[.=0]/text()">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

https://xsltfiddle.liberty-development.net/3MP42Pc/4

不过,使用后裔或自我对我来说是新的

于 2021-11-09T11:58:55.527 回答
0

要获得您(显然)期望的结果,同时使用:

<xsl:mode on-no-match="shallow-skip" />

默认情况下,您必须制作模板:

<xsl:template match="*[descendant-or-self::status=0] | status[.=0]/text()">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

为了完整地复制通向<status>0</status>叶子的所有分支。


如前所述,制作起来要简单得多:

<xsl:mode on-no-match="shallow-copy" />

默认值。然后你只需要添加:

<xsl:template match="*[not(descendant-or-self::status=0)]"/>

为了压制没有<status>0</status>叶子的树枝。

于 2021-11-09T12:07:43.420 回答