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

时间:2016-03-23 14:57:16

标签: xml xpath xslt-1.0

假设我有以下列表:

<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>

一个重要的事情,我不知道什么值会有type属性!它将以编程方式生成。 Not this one.我只知道某些商品可能具有相同的属性。

我想将此列表转换为:

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

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

2 个答案:

答案 0 :(得分:2)

您想按类别对项目进行分组。使用密钥轻松完成分组:

migrations

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

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

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

可以表达为:

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

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

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

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

在XPath中,这是<xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])"> (节点集永远不能包含两次相同的节点)

所以这个:

. | key('byType', @type)

输出

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

答案 1 :(得分:1)

您想使用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进行分组。如果未设置@type,则只需打印该项目。否则,遍历item的所有@type并打印它们。