在 XSL 文档中,我需要根据其值对 image 元素进行分组:
事实证明,这对我来说实施起来非常棘手。
对于工具,我在 .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>
...所以三个 **图像 ** 元素中的最后一个丢失了。
我尝试了很多方法,但很容易破坏逻辑:一个元素是第二次出现还是完全被省略。 想知道我是否遗漏了一些简单的东西,或者是否有一种更简单的方法来处理这种分组。
假设处理相邻半图像的每个部分的规则是按现有顺序将它们配对,只保留一组中的最后一个奇数,您可以使用称为“兄弟递归”的技术来实现它:
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>