Xslt 当属性具有特定值时从元素中移除属性
我正在编写一个样式表来“规范化”XML模式,以便比较它们。它将按名称、顺序属性(按固定顺序)等对顶级元素进行排序。这是到目前为止我对属性所做的:Xslt 当属性具有特定值时从元素中移除属性,xslt,xsd,xslt-2.0,Xslt,Xsd,Xslt 2.0,我正在编写一个样式表来“规范化”XML模式,以便比较它们。它将按名称、顺序属性(按固定顺序)等对顶级元素进行排序。这是到目前为止我对属性所做的: <xsl:template match="xsd:attribute"> <xsl:copy> <xsl:copy-of select="@name"/> <xsl:copy-of select="@type"/> <xsl:cop
<xsl:template match="xsd:attribute">
<xsl:copy>
<xsl:copy-of select="@name"/>
<xsl:copy-of select="@type"/>
<xsl:copy-of select="@ref"/>
<xsl:copy-of select="@use"/>
<xsl:copy-of select="@default"/>
<xsl:apply-templates select="@*">
<xsl:sort select="name()"/>
</xsl:apply-templates>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
现在,我还想删除冗余属性。例如,应该删除use=“optional”
,因为optional
是默认值
因此,我的问题是:当
属性的值为optional
时,为了删除use
属性,增强上述代码的最简单方法是什么 @JohnBollinger和@MartinHonnen正确地指出,@*
条件将插入所有属性,甚至是上面选择的属性。因此,必须改进条件。还有人指出,根据该规范,无法确保属性的顺序。他们被订购的事实只是我的处理器(Saxon9He)如何工作的一个假象。不过我对这个没意见。以下是我得出的解决方案:
<xsl:template match="xsd:attribute">
<xsl:copy>
<xsl:copy-of select="@name" />
<xsl:copy-of select="@type" />
<xsl:copy-of select="@ref" />
<xsl:copy-of select="@use[string() != 'optional']" />
<xsl:copy-of select="@default" />
<xsl:apply-templates select="@*[name(.) != 'use']">
<xsl:sort select="name()" />
</xsl:apply-templates>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
我没有将其他属性名称添加到@*
上的负过滤器中,因为Saxon不会复制属性,即使它被@*
子句重新插入,也不会按要求的顺序保留它们。因此,这确实以最少的努力满足了我目前的需求,即使它不是一个通用的解决方案(我实际上并不需要)。@JohnBollinger和@MartinHonnen正确地指出,@*
条件将插入所有属性,甚至是上面选择的属性。因此,必须改进条件。还有人指出,根据该规范,无法确保属性的顺序。他们被订购的事实只是我的处理器(Saxon9He)如何工作的一个假象。不过我对这个没意见。以下是我得出的解决方案:
<xsl:template match="xsd:attribute">
<xsl:copy>
<xsl:copy-of select="@name" />
<xsl:copy-of select="@type" />
<xsl:copy-of select="@ref" />
<xsl:copy-of select="@use[string() != 'optional']" />
<xsl:copy-of select="@default" />
<xsl:apply-templates select="@*[name(.) != 'use']">
<xsl:sort select="name()" />
</xsl:apply-templates>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
我没有将其他属性名称添加到@*
上的负过滤器中,因为Saxon不会复制属性,即使它被@*
子句重新插入,也不会按要求的顺序保留它们。因此,即使这不是一个通用的解决方案(我实际上并不需要),它也能以最少的努力满足我目前的需求。属性在XSLT/XPath/XQuery数据模型中没有排序。另外,您希望通过对某些属性使用不同的copy of
,然后将模板应用于所有属性来实现什么?我建议使用apply templates
而不是copy of
来转换属性,当指定的属性实际上不存在于上下文节点上时,
的复制将失败。然后,每个属性模板还可以为您提供适当的杠杆,用于忽略采用默认值的属性——在这种情况下,它们可以转换为零。它按照列出的顺序对指定的属性进行排序(因此,首先是名称
,然后是类型
,然后是参考
,等等)。任何其他未明确命名的属性都将按名称排序(这是apply templates select=“@*”
所做的)。否,@pegasus。首先,属性顺序在相关数据模型中不重要。如果您碰巧按照元素副本出现的词法顺序可靠地获取属性,那么这是特定XSLT处理器的一个特征,而不是XSLT语言提供的保证。其次,apply templates
将转换所有属性,不仅仅是那些尚未成为复制
元素主题的属性。您的应用模板
处理所有属性,包括您已经尝试输出的属性,这样,由于WinSatAttribute中的第9点,应用模板的最后一步不会在XSLT/XPath/XQuery数据模型中排序。另外,您希望通过对某些属性使用不同的copy of
,然后将模板应用于所有属性来实现什么?我建议使用apply templates
而不是copy of
来转换属性,当指定的属性实际上不存在于上下文节点上时,
的复制将失败。然后,每个属性模板还可以为您提供适当的杠杆,用于忽略采用默认值的属性——在这种情况下,它们可以转换为零。它按照列出的顺序对指定的属性进行排序(因此,首先是名称
,然后是类型
,然后是参考
,等等)。任何其他未明确命名的属性都将按名称排序(这是apply templates select=“@*”
所做的)。否,@pegasus。首先,属性顺序在相关数据模型中不重要。如果您碰巧按照元素副本出现的词法顺序可靠地获取属性,那么这是特定XSLT处理器的一个特征,而不是XSLT语言提供的保证。其次,apply templates
将转换所有属性,不仅仅是那些尚未成为<代码>元素副本主题的属性。您的<代码>应用模板<代码>处理所有属性,包括您已经尝试输出的属性,这样,由于wins<代码>选择=“@*[name(!='use']”中的第9点,应用模板的最后一步就开始了
可以优雅地写成XSLT/XPath 2及更高版本中的select=“@*除了@use”
。select=“@*[name(.)!='use']”可以是