xslt顺序和分组,每个组使用
我试图在对每个组使用xslt顺序和分组,每个组使用,xslt,saxon,Xslt,Saxon,我试图在对每个组使用时对嵌套的分组和排序有所了解。 我的想法是首先由制作人对项目进行排序和分组。然后,当我有了这个制作人组时,我想按code对每个组进行排序。然而,目前code的顺序并不像我想的那样有效。在下面的示例中,问题在于项与code=01001-064-03有关。它应该与所有其他项目一起分组,这些项目的code以01001开头,但不是。如果我将整个项/code[text()='01001-064-03'](最后一个)移动到xml的开头,则分组工作正常 请问我的问题是什么 谢谢 <i
时对嵌套的分组和排序有所了解。
我的想法是首先由制作人对项目进行排序和分组。然后,当我有了这个制作人
组时,我想按code
对每个组进行排序。然而,目前code
的顺序并不像我想的那样有效。在下面的示例中,问题在于项与code=01001-064-03
有关。它应该与所有其他项目一起分组,这些项目的code
以01001
开头,但不是。如果我将整个项/code[text()='01001-064-03']
(最后一个)移动到xml的开头,则分组工作正常
请问我的问题是什么
谢谢
<items>
<change_date>#11.11.2020 7:42:13</change_date>
<result>
<item>
<code>01001-064-01</code>
<producer>prod1</producer>
</item>
<item>
<code>01001-064-02</code>
<producer>prod1</producer>
</item>
<item>
<code>def</code>
<producer>prod1</producer>
</item>
<item>
<code>ghi</code>
<producer>prod2</producer>
</item>
<item>
<code>jkl</code>
<producer>prod3</producer>
</item>
<item>
<code>abc</code>
<producer>prod3</producer>
</item>
<item>
<code>def</code>
<producer>prod4</producer>
</item>
<item>
<code>ghi</code>
<producer>prod4</producer>
</item>
<item>
<code>jkl</code>
<producer>prod5</producer>
</item>
<item>
<code>01001-064-03</code>
<producer>prod1</producer>
</item>
</result>
</items>
我的想法是首先由制作人对项目进行排序和分组。然后,当我有了这个制作人
组时,我想按code
对每个组进行排序
如果这就是你想要做的,为什么还不足以做到:
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="result">
<xsl:for-each-group select="item" group-by="producer">
<xsl:sort select="producer"/>
<group>
<xsl:apply-templates select="current-group()">
<xsl:sort select="code"/>
</xsl:apply-templates>
</group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
我正在使用XSLT2.0和saxon he 10.3
实际上,您使用的是XSLT 3.0。也许一个组合的分组就足够了:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-skip"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="change_date"/>
<xsl:template match="result">
<data>
<xsl:for-each-group select="item" composite="yes" group-by="producer, code => replace('[^a-z0-9].*$', '', 'i')">
<xsl:sort select="producer"/>
<xsl:sort select="code"/>
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:for-each-group>
</data>
</xsl:template>
<xsl:template match="item">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
这就是Saxon 9.8和更高版本(例如Saxon 10)支持的XSLT 3,如果您真的需要使用XSLT 2.0处理器,那么每个group group by的嵌套或串联分组键可以实现与上述XSLT 3中的复合分组键相同的效果。因为有生产者的后处理。基本上,一个生产商可以有多个组。分组基于功能mf:相同产品
,因此,如果一个项目的code
与另一个项目的code
匹配,则应该有一个新组。是的,我使用的xslt版本是错误的。请编辑您的问题,并(1)用文字解释您要应用的逻辑和(2)添加预期结果。希望修改后的结果现在能更好地描述给我看,每个组第二个中的排序或分组似乎不能正常工作。您给我们的是一个示例,而不是一个规则。对于每个组的两个嵌套
,内部尝试传入前面的同级::item
不一定会选择外部分组的current-group()
中的项,因为同级基于XML输入的文档顺序,而不是分组填充的顺序。因此,这可能是代码没有按您的要求执行的原因。我仍然想知道你是否需要比较分组中的两个项目,你能不能推断出每个项目的代码
的相关部分,然后在分组中使用该部分,或者分组相邻的项目
?你能给出一些方法吗?这个分组对我来说是新的。请记住,两个不同的生产商可以有相似的产品代码。再次感谢。我尝试了“按多个属性选择”,但我记得它不起作用,所以我从未想过该组会起作用。您提供的解决方案非常简单。仅仅是一个问题前面的兄弟姐妹
不能像当前-组()/前面的兄弟姐妹…
?你可以使用当前-组()/前面的兄弟姐妹::item
或者当前-组()/前面的兄弟姐妹::*
当然,但是兄弟姐妹轴是在节点树上定义的;根据您想要实现的目标,导航当前组中节点的同级可能有意义,但它在输入树中导航,而不是在节点序列中导航。因此,对于…
和当前-group()
元素,例如a
和c
元素,表达式current-group()/前面的同级::*
将包括不属于该组的b
元素。
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="result">
<xsl:for-each-group select="item" group-by="producer">
<xsl:sort select="producer"/>
<group>
<xsl:apply-templates select="current-group()">
<xsl:sort select="code"/>
</xsl:apply-templates>
</group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-skip"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="change_date"/>
<xsl:template match="result">
<data>
<xsl:for-each-group select="item" composite="yes" group-by="producer, code => replace('[^a-z0-9].*$', '', 'i')">
<xsl:sort select="producer"/>
<xsl:sort select="code"/>
<group>
<xsl:apply-templates select="current-group()" />
</group>
</xsl:for-each-group>
</data>
</xsl:template>
<xsl:template match="item">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>