提问人:deuri 提问时间:11/17/2023 更新时间:11/17/2023 访问量:32
如何使用 xslt 1.0 根据子元素值拆分 xml 元素的分组
How to split grouping of xml elements based on their subelement values using xslt 1.0
问:
在 XSL 文档中,我需要根据图像元素的值对图像元素进行分组:
- size=full 的元素在图像集中应该是单独的。
- size=half 的元素应该在图像集中...
- 成对,如果有两个相邻的图像元素的 size=half
- 如果不是的话,独自一人。
事实证明,这对我来说非常棘手。
对于工具,我在 .NET 4.8 软件中使用了标准的 XSLT 1.0 引擎。
源数据:
<?xml version="1.0" encoding="UTF-8" ?>
<imagecollection>
<imageset>
<image>
<size>half</size>
<id>a group 1</id>
</image>
<image>
<size>half</size>
<id>b group 1</id>
</image>
<image>
<size>full</size>
<id>c group 2</id>
</image>
<image>
<size>half</size>
<id>d group 3</id>
</image>
<image>
<size>full</size>
<id>e group 4</id>
</image>
<image>
<size>full</size>
<id>f group 5</id>
</image>
<image>
<size>half</size>
<id>g group 6</id>
</image>
</imageset>
</imagecollection>
我最终完成了这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="imagecollection">
<imagecollection>
<xsl:for-each select="imageset/image[not(preceding-sibling::image[1][size='half'] and size='half')]">
<imageset>
<xsl:copy-of select="."/>
<xsl:if test="following-sibling::image[1][size='half'] and size='half'">
<xsl:copy-of select="following-sibling::image[1]"/>
</xsl:if>
</imageset>
</xsl:for-each>
</imagecollection>
</xsl:template>
</xsl:stylesheet>
事实上,我使用上面的数据得到了正确的结果:
<imagecollection>
<imageset>
<image>
<size>half</size>
<id>a group 1</id>
</image>
<image>
<size>half</size>
<id>b group 1</id>
</image>
</imageset>
<imageset>
<image>
<size>full</size>
<id>c group 2</id>
</image>
</imageset>
<imageset>
<image>
<size>half</size>
<id>d group 3</id>
</image>
</imageset>
<imageset>
<image>
<size>full</size>
<id>e group 4</id>
</image>
</imageset>
<imageset>
<image>
<size>full</size>
<id>f group 5</id>
</image>
</imageset>
<imageset>
<image>
<size>half</size>
<id>g group 6</id>
</image>
</imageset>
</imagecollection>
然而,转换无法处理的是这个简单的数据:
<?xml version="1.0" encoding="UTF-8" ?>
<imagecollection>
<imageset>
<image>
<size>half</size>
<id>a group 1</id>
</image>
<image>
<size>half</size>
<id>b group 1</id>
</image>
<image>
<size>half</size>
<id>c group 2</id>
</image>
</imageset>
</imagecollection>
我的转换给出了这个输出:
<imagecollection>
<imageset>
<image>
<size>half</size>
<id>a group 1</id>
</image>
<image>
<size>half</size>
<id>b group 1</id>
</image>
</imageset>
</imagecollection>
...因此,缺少三个图像元素中的最后一个。
我尝试了很多东西,但很容易打破逻辑:一个元素是第二次出现还是完全省略。 想知道我是否遗漏了一些简单的东西,或者一开始是否更容易处理这种分组。
答:
1赞
michael.hor257k
11/17/2023
#1
假设处理相邻半图像的每个部分的规则是按现有顺序将它们配对,只留下最后一个奇数图像在自己的集合中,您可以使用一种称为“同级递归”的技术来实现它:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/imagecollection">
<imagecollection>
<!-- start with first image -->
<xsl:apply-templates select="imageset/image[1]"/>
</imagecollection>
</xsl:template>
<!-- first half of pair -->
<xsl:template match="image[size='half' and following-sibling::image[1]/size='half']">
<imageset>
<!-- copy self and other half -->
<xsl:copy-of select="."/>
<xsl:copy-of select="following-sibling::image[1]"/>
</imageset>
<!-- skip to sibling after next -->
<xsl:apply-templates select="following-sibling::image[2]"/>
</xsl:template>
<!-- full or standalone half -->
<xsl:template match="image">
<imageset>
<xsl:copy-of select="."/>
</imageset>
<!-- continue recursion with following sibling -->
<xsl:apply-templates select="following-sibling::image[1]"/>
</xsl:template>
</xsl:stylesheet>
评论
id