使用 XPath,select parent 代替,如果所有 children 都被 selected
With XPath, select parent instead, if all children are selected
我有一个删除元素的样式表 (XSLT 2.0)。现在我有一个问题,我是 XML "pruning" 的 DTD 不允许我删除某个节点下的所有元素,而不删除空节点。因此,如果删除了所有子元素,我也想删除父元素。我想 select 使用 XPath 表达式删除要删除的元素。
举个例子,考虑这个 XML(没有提供 DTD,但基本上说明一个盒子必须包含至少一支蜡笔):
<?xml version="1.0" encoding="UTF-8"?>
<test>
<box>
<crayon color="red"/>
<crayon color="red"/>
<crayon color="red"/>
<crayon/>
</box>
<box>
<crayon/>
<crayon/>
</box>
<box>
<crayon color="red"/>
<crayon color="red"/>
</box>
<box>
<crayon color="red"/>
<crayon color="red"/>
<crayon color="red"/>
<crayon/>
</box>
</test>
我想要的输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<box>
<crayon/>
</box>
<box>
<crayon/>
<crayon/>
</box>
<box>
<crayon/>
</box>
</test>
不幸的是,这是一个样式表,它不符合我的要求,但显示了我想要实现的形式:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Next row should apply to sets of crayons or complete boxes. -->
<xsl:template match="//box[if (count(crayon[@color = 'red']) = count(crayon)) then (.) else (crayon[@color = 'red'])]"/>
</xsl:stylesheet>
我想使用一个 XPath 表达式来管理它的原因是我有一个生成样式表的函数,将 XPath 作为输入参数。
XSLT 3(受 Saxon 9.8 或 Altova 2017 或 2018 或 Exselt 支持)是一个选项吗?在那里你可以利用新的 xsl:where-populated
(https://www.w3.org/TR/xslt/#element-where-populated):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="box">
<xsl:where-populated>
<xsl:next-match/>
</xsl:where-populated>
</xsl:template>
<xsl:template match="box/crayon[@color = 'red']"/>
</xsl:stylesheet>
http://xsltfiddle.liberty-development.net/6qM2e2g
我不太确定您需要在哪一部分为我们设置参数或变量,但具有浅层属性的 XSLT 3 也简化了该任务。
使用 XSLT 2 我想你可以使用
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="box[not(crayon[not(@color = 'red')])] | box/crayon[@color = 'red']"/>
</xsl:transform>
我有一个删除元素的样式表 (XSLT 2.0)。现在我有一个问题,我是 XML "pruning" 的 DTD 不允许我删除某个节点下的所有元素,而不删除空节点。因此,如果删除了所有子元素,我也想删除父元素。我想 select 使用 XPath 表达式删除要删除的元素。
举个例子,考虑这个 XML(没有提供 DTD,但基本上说明一个盒子必须包含至少一支蜡笔):
<?xml version="1.0" encoding="UTF-8"?>
<test>
<box>
<crayon color="red"/>
<crayon color="red"/>
<crayon color="red"/>
<crayon/>
</box>
<box>
<crayon/>
<crayon/>
</box>
<box>
<crayon color="red"/>
<crayon color="red"/>
</box>
<box>
<crayon color="red"/>
<crayon color="red"/>
<crayon color="red"/>
<crayon/>
</box>
</test>
我想要的输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<box>
<crayon/>
</box>
<box>
<crayon/>
<crayon/>
</box>
<box>
<crayon/>
</box>
</test>
不幸的是,这是一个样式表,它不符合我的要求,但显示了我想要实现的形式:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Next row should apply to sets of crayons or complete boxes. -->
<xsl:template match="//box[if (count(crayon[@color = 'red']) = count(crayon)) then (.) else (crayon[@color = 'red'])]"/>
</xsl:stylesheet>
我想使用一个 XPath 表达式来管理它的原因是我有一个生成样式表的函数,将 XPath 作为输入参数。
XSLT 3(受 Saxon 9.8 或 Altova 2017 或 2018 或 Exselt 支持)是一个选项吗?在那里你可以利用新的 xsl:where-populated
(https://www.w3.org/TR/xslt/#element-where-populated):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="box">
<xsl:where-populated>
<xsl:next-match/>
</xsl:where-populated>
</xsl:template>
<xsl:template match="box/crayon[@color = 'red']"/>
</xsl:stylesheet>
http://xsltfiddle.liberty-development.net/6qM2e2g
我不太确定您需要在哪一部分为我们设置参数或变量,但具有浅层属性的 XSLT 3 也简化了该任务。
使用 XSLT 2 我想你可以使用
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="box[not(crayon[not(@color = 'red')])] | box/crayon[@color = 'red']"/>
</xsl:transform>