当以编程方式生成属性时,如何选择具有特定属性的所有元素



假设我有以下列表:

<list>
  <item>text1</item>
  <item>text2</item>
  <item>text3</item>
  <item type="type1">text4</item>
  <item type="type1">text5</item>
  <item type="type1">text6</item>
  <item>text7</item>
  <item>text8</item>
  <item type="type2">text9</item>
  <item type="type2">text10</item>
  <item>text11</item>
  <item>text12</item>
  <item type="...">...</item>
  ...
  <item>...</item>
  ...
</list>

重要的一点是,我不知道什么值会有类型属性!它将以编程方式生成。不是这个。我只知道有些项目可能具有相同的属性

我想把这个列表转换成:

  text1
  text2
  text3
  text4, text5, text6
  text7
  text8
  text9, text10
  text11
  text12

所以,对于每个并没有"type"属性的项,我只输出项中的文本。对于每个具有相同属性的项目,我在一行中输出所有项目文本。如何在xslt中实现这一点?当属性以编程方式生成时,如何选择具有相同属性的所有项?

您希望按类型对项目进行分组。分组很容易用一个键完成:

<xsl:key name="byType" match="item[@type]" use="@type" />

这将创建具有类型的所有项的索引,使用它们各自的类型作为键。

接下来,只有当以下两个条件之一为真时,才需要生成输出行:

  • 项目没有类型,或者
  • 该项目是其类型中的第一个

可以表示为:

<xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])">

其类型的第一个项目将输出所有其他项目,这些项目用逗号分隔。以下相同类型的项目不应输出任何内容(因为它们已经打印)。

我们可以将要在每行打印的项目列表定义为这两个节点集的并集:

  • 当前项目(对于项目没有类型的情况)
  • 与当前项目具有相同类型的所有项目(通过键)

在XPath中,这是. | key('byType', @type)(节点集永远不能两次包含同一节点)

所以这个:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="UTF-8" />
    <xsl:key name="byType" match="item[@type]" use="@type" />
    <xsl:template match="/*">
        <xsl:apply-templates select="item" />
    </xsl:template>
    <xsl:template match="item">
        <xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])">
            <xsl:for-each select=". | key('byType', @type)">
                <xsl:value-of select="." />
                <xsl:if test="position() &lt; last()">, </xsl:if>
            </xsl:for-each>
            <xsl:text>&#xA;</xsl:text>
        </xsl:if>
    </xsl:template>
</xsl:transform>

输出

文本1文本2文本3text4、text5、text6文本7文本8text9,text10文本11文本12。。。。。。

您想要使用Muenchian分组。像这样的东西应该工作

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
    <xsl:key name="items-by-type" match="item" use="@type" />
    <xsl:template match="/list">

        <xsl:for-each select="item[count(. | key('items-by-type', @type)[1]) = 1]">
            <xsl:if test="not(@type)">
                <xsl:value-of select="."/> 
                <xsl:text>&#10;</xsl:text>
            </xsl:if>
            <xsl:if test="@type">
                <xsl:for-each select="key('items-by-type', @type)">
                    <xsl:value-of select="." />    
                    <xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
                </xsl:for-each>                
                <xsl:text>&#10;</xsl:text>
            </xsl:if>
        </xsl:for-each>

    </xsl:template>
</xsl:transform>

http://xsltransform.net/3NJ3914/3

使用keyitem s进行分组。如果未设置@type,则只打印项目。否则,迭代该@type的所有item并打印它们。

相关内容

  • 没有找到相关文章

最新更新