XSLT 按变量分组

XSLT group by variable

输入:

  <?xml version="1.0" encoding="UTF-8"?>
<output>
  <input>
    <!--details-->
</input>
 <meta2>
    <Comenzi>
        <output_getquerydata>
            <queries>
                <query name="part1">
                    <parameters>
                        <!--details-->
                    </parameters>
                    <queryErrors>
                        <!--details-->
                    </queryErrors>
                    <queryResults>
                        <record id="1">
                            <column name="id_schedule">3</column>
                            <column name="VRIdTask">1319648</column>
                            <column name="MSSinergieOrderP"/>
                            <column name="MSSinergieTaskP"/>
                            <column name="VRPlanId">11310337</column>
                            <column name="TripLabel">189221</column>
                            <column name="MSSinergieOrderNP"/>
                            <column name="MSSinergieTaskNP"/>
                        </record>
                        <record id="2">
                            <column name="id_schedule">3</column>
                            <column name="VRIdTask">1319652</column>
                            <column name="MSSinergieOrderP">1320566</column>
                            <column name="MSSinergieTaskP">1319575</column>
                            <column name="VRPlanId">11310281</column>
                            <column name="TripLabel">189221</column>
                            <column name="MSSinergieOrderNP"/>
                            <column name="MSSinergieTaskNP"/>
                        </record>
                        <record id="3">
                            <column name="id_schedule">3</column>
                            <column name="VRIdTask">1319652</column>
                            <column name="MSSinergieOrderP">1320614</column>
                            <column name="MSSinergieTaskP">1319623</column>
                            <column name="VRPlanId">11310281</column>
                            <column name="TripLabel">189221</column>
                            <column name="MSSinergieOrderNP"/>
                            <column name="MSSinergieTaskNP"/>
                        </record>
                        <record id="4">
                            <column name="id_schedule">3</column>
                            <column name="VRIdTask">1319652</column>
                            <column name="MSSinergieOrderP">1320656</column>
                            <column name="MSSinergieTaskP">1319667</column>
                            <column name="VRPlanId">11310281</column>
                            <column name="TripLabel">189221</column>
                            <column name="MSSinergieOrderNP"/>
                            <column name="MSSinergieTaskNP"/>
                        </record>
                    </queryResults>
                </query>
            </queries>
        </output_getquerydata>
    </Comenzi>
    </meta2>
  </output>

XSL:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" /> 
    <xsl:template name="task-attr">
    <!--parameter to filter per VRPlanId-->     
    <xsl:param name="param.VRPlanId"/>              
    <xsl:variable name="var.mstp">                      
        <xsl:for-each 


  select="/output/meta2/Comenzi/output_getquerydata/queries/query/queryResults/rec
    ord[column[@name='VRPlanId'] = $param.VRPlanId]">
             <!--preventing empty blocks and duplicates for MSTP-->          
             <xsl:if test="string-length(column[@name='MSSinergieTaskP']) &gt;0 
    and not(preceding::record[column[@name='MSSinergieTaskP']/text() = 
    current()/column[@name='MSSinergieTaskP']/text()])">                   
                <xsl:value-of select="concat(column[@name='MSSinergieTaskP'], 
    ',')"/>              
            </xsl:if>                                       
        </xsl:for-each>                             
       </xsl:variable>     
     <xsl:variable name="var.msonpc">                        
        <xsl:for-each 

 select="/output/meta2/Comenzi/output_getquerydata/queries/query/queryResults/re
    cord[column[@name='VRPlanId'] = $param.VRPlanId]">
            <!--preventing empty blocks and duplicates for MSONPC-->            
            <xsl:if test="string-length(column[@name='MSSinergieTaskNP']) &gt;0 
    and not(preceding::record[column[@name='MSSinergieTaskNP']/text() = 
    current()/column[@name='MSSinergieTaskNP']/text()])">                 
                <xsl:value-of select="concat(column[@name='MSSinergieTaskNP'], 
    ',')"/>                
            </xsl:if>                                       
        </xsl:for-each>                             
     </xsl:variable>
     <!--concat all non-duplicates MSTP and MSONPC without last delimiter--> 
     <xsl:value-of select="concat($var.mstp, substring($var.msonpc, 1, string-
    length($var.msonpc)-1))"/>     
    </xsl:template>

    <xsl:template match="/">        
     <output>            
        <xsl:for-each 

 select="/output/meta2/Comenzi/output_getquerydata/queries/query/queryResults/record">             
             <xsl:if test ="not(preceding::record[column[@name='VRPlanId']/text() = 
    current()/column[@name='VRPlanId']/text()])">                    
                 <xsl:variable name="task.id">                                                   
                    <xsl:call-template name="task-attr">
                        <!--as input parameter put non-duplicate VRPlanId-->                                                            
                        <xsl:with-param name="param.VRPlanId" 
   select="column[@name='VRPlanId']"/>                                                   
                    </xsl:call-template>                                    
                </xsl:variable>
                <!--if all non-duplicates MSTP and MSONPC will be blank block 
   Cdo won't be created-->                   
                 <xsl:if test="string-length($task.id) &gt;0">                       
                     <Cdo>                           
                        <parameters>                                
                            <task>                                                          
                                <xsl:attribute name="id">                                                       
                                    <xsl:value-of select="$task.id"/>               
                                </xsl:attribute>                                
                            </task>                             
                            <action>                                                            
                                <xsl:attribute name="id">                                                                           
                                    <xsl:value-of 
  select="column[@name='VRPlanId']"/>                                                               
                                </xsl:attribute>                                
                            </action>                                           
                        </parameters>                       
                    </Cdo>                                      
                </xsl:if>               
            </xsl:if>           
        </xsl:for-each>                     
      </output>   
    </xsl:template>
    </xsl:stylesheet>

大家好,

感谢您的帮助。 目标是检查我们构建标签的每个不同的 VRPlanID 值 如果标签的 id 部分中没有 null/empty,则将相应的 MSTP、MSONPC(不同)分组。 因此,我们在 VRPlanID 之后分组,然后从 MSTP/MSONPC 中的每条记录中获取不同的值。 如果它们是空的,那么只需构建一个虚拟/空 message/tag。 这有效,但我有 2 个问题: - 我总是在最后一个 ID 后得到一个 ',' 逗号,我不明白为什么 - 我不再需要串联,但我想为每个 ID 设置一个标签任务

因此,所需的输出将是:

    <output>
    <Cdo>
        <parameters>
            <task id="1319575"/>
            <task id="1319623"/>
            <task id="1319667"/>
            <action id="11310281"/>
        </parameters>
    </Cdo>
</output>

请记住,标签 MSInergieTaskP 和 MSInergieTaskNP 之间的任何组合都是可能的。所以一个可能是空的,另一个不是。或者只为一条记录留空,然后为下一条记录提供值。 我只是想为每个不同的 VRIdTask 获取任何组合的不同值。

我似乎无法让它工作。 请问有什么建议吗?

对于 XSLT 1.0 中的分组,最有效的解决方案是使用 muenchian grouping

在这种情况下,您可以使用属性 @name='VRPlanId'.

中的值创建一个 分组键
<xsl:key name="vrPlanId" match="record" use="column[@name='VRPlanId']" />

然后使用键对节点进行分组

<xsl:apply-templates select="//record[generate-id() = generate-id(key('vrPlanId', column[@name='VRPlanId'])[1])]" />

所以output模板修改为

<xsl:template match="output">
    <xsl:copy>
        <Cdo>
            <parameters>
                <xsl:apply-templates select="//record[generate-id() = generate-id(key('vrPlanId', column[@name='VRPlanId'])[1])]" />
            </parameters>
        </Cdo>
    </xsl:copy>
</xsl:template>

对于 record 模板,检查 MSSinergieTaskPMSSinergieTaskNP 中是否有任何值,然后循环遍历分组节点以从 MSSinergieTaskP 中获取值。

下面是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:key name="vrPlanId" match="record" use="column[@name='VRPlanId']" />

    <xsl:template match="output">
        <xsl:copy>
            <Cdo>
                <parameters>
                    <xsl:apply-templates select="//record[generate-id() = generate-id(key('vrPlanId', column[@name='VRPlanId'])[1])]" />
                </parameters>
            </Cdo>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="record">
        <xsl:if test="column[@name='MSSinergieTaskP'] != '' or column[@name='MSSinergieTaskNP'] != ''">
            <action>
                <xsl:attribute name="id">
                    <xsl:value-of select="column[@name='VRPlanId']" />
                </xsl:attribute>
            </action>
            <xsl:for-each select="key('vrPlanId', column[@name='VRPlanId'])">
                <task>
                    <xsl:attribute name="id">
                        <xsl:value-of select="column[@name='MSSinergieTaskP']" />
                    </xsl:attribute>
                </task>
            </xsl:for-each>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

这提供了所需的输出

<output>
    <Cdo>
        <parameters>
            <action id="11310281" />
            <task id="1319575" />
            <task id="1319623" />
            <task id="1319667" />
        </parameters>
    </Cdo>
</output>