XSLT 1.0组和计数节点

wal*_*234 0 xml xslt

我有XML模块,里面有一些部分....

<?xml version="1.0"?>
<root>
 <modul id="1">
    <part id="01" part_number="AAA"/>
    <part id="02" part_number="AAA"/>
    <part id="03" part_number="AAA"/>
    <part id="04" part_number="BBB"/>
 </modul>
 <modul id="2">
    <part id="05" part_number="AAA"/>
    <part id="06" part_number="AAA"/>
    <part id="07" part_number="CCC"/>
    <part id="08" part_number="BBB"/>
 </modul>
</root>
Run Code Online (Sandbox Code Playgroud)

我想在每个模块中按part_number分组并计算节点的出现次数:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="keyPartNumber" match="part" use="@part_number"/>
<xsl:template match="/">
<xsl:for-each select="root/modul">
<modul name="{@id}">
<xsl:for-each select="part[generate-id() = generate-id(key('keyPartNumber',@part_number)[1])]">
  <xsl:sort select="@part_number" order="ascending" data-type="text"/>                        
  <node title="{@part_number} (quantity: {count(key('keyPartNumber',@part_number))})" />
  </xsl:for-each>
</modul>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

但结果我得到的不是我想要的:

<?xml version="1.0" encoding="UTF-8"?>
<modul name="1">
  <node title="AAA (quantity: 5)"/>
  <node title="BBB (quantity: 2)"/>
</modul>
<modul name="2">
  <node title="CCC (quantity: 1)"/>
</modul>
Run Code Online (Sandbox Code Playgroud)

例外结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<modul name="1">
  <node title="AAA (quantity: 3)"/>
  <node title="BBB (quantity: 1)"/>
</modul>
<modul name="2">
  <node title="AAA (quantity: 2)"/>
  <node title="BBB (quantity: 1)"/>
  <node title="CCC (quantity: 1)"/>
</modul>
Run Code Online (Sandbox Code Playgroud)

我怎么能意识到这一点?是否可以动态创建每个模块的密钥?

Tim*_*m C 5

这是因为您需要将模块 ID作为键的一部分包含在内,以便部件按模块进行区分

<xsl:key name="keyPartNumber" match="part" use="concat(../@id, '|', @part_number)"/>
Run Code Online (Sandbox Code Playgroud)

注意|这里可以是任何东西,只要它不在id或part_number中出现.

每次访问密钥时都会使用相同的concat语句.

试试这个XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="keyPartNumber" match="part" use="concat(../@id, '|', @part_number)"/>

    <xsl:template match="/">
        <xsl:for-each select="root/modul">
            <modul name="{@id}">
                <xsl:for-each select="part[generate-id() = generate-id(key('keyPartNumber',concat(../@id, '|', @part_number))[1])]">
                    <xsl:sort select="@part_number" order="ascending" data-type="text"/>                        
                    <node title="{@part_number} (quantity: {count(key('keyPartNumber',concat(../@id, '|', @part_number)))})" />
                </xsl:for-each>
            </modul>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)