【问题标题】:XSLT group if condition is matchedXSLT 组(如果条件匹配)
【发布时间】:2017-12-12 03:27:52
【问题描述】:

输入:

  <?xml version="1.0" encoding="UTF-8"?>
<output>
<input>
    <!--details-->
</input>
<meta2>
    <tag>
        <output_getquerydata>
            <queries>
                <query name="part1">
                    <parameters>
                        <!--details-->
                    </parameters>
                    <queryErrors>
                        <!--details-->
                    </queryErrors>
                    <queryResults>
                        <record id="1">                              
                            <column name="VRIdTask">1</column>                               
                            <column name="MSTP">22</column>
                            <column name="VRPlanId">11310224</column>                                
                            <column name="MSONPC">221</column> 
                        </record>
                        <record id="2">
                            <column name="VRIdTask">1</column>
                            <column name="MSTP">22</column>
                            <column name="VRPlanId">11310224</column> 
                            <column name="MSONPC">2211</column> 
                        </record>
                        <record id="3"> 
                            <column name="VRIdTask">3</column> 
                            <column name="MSTP"/>
                            <column name="VRPlanId">11310337</column> 
                            <column name="MSONPC"/> 
                        </record>
                        <record id="4"> 
                            <column name="VRIdTask">2</column> 
                            <column name="MSTP"/>
                            <column name="VRPlanId">11310281</column> 
                            <column name="MSONPC">2221</column> 
                        </record>
                        <record id="5"> 
                            <column name="VRIdTask">4</column> 
                            <column name="MSTP">33</column>
                            <column name="VRPlanId">11310281</column> 
                            <column name="MSONPC">222221</column> 
                        </record>
                        <record id="6"> 
                            <column name="VRIdTask">4</column> 
                            <column name="MSTP">331</column>
                            <column name="VRPlanId">11310281</column> 
                            <column name="MSONPC">222221</column> 
                        </record>
                    </queryResults>
                </query>
            </queries>
        </output_getquerydata>
    </tag>
</meta2>
</output>

XSL:

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k" match="output/meta2/tag/output_getquerydata/queries/query/queryResults/record" use="./column[@name='VRPlanId']"/>
<xsl:template match="@*|node()">
    <xsl:variable name="distinctOrder" select="//record[string(column[@name='VRPlanId'])][count(. | key('k', column[@name='VRPlanId'])[1]) >1]"/>
    <xsl:if test="count(key('k', .//column[@name='VRPlanId'])) >0 or //queryError">
        <Cdo>
            <parameters>
                <xsl:for-each select="$distinctOrder">
                    <task id="{concat(column[@name='MSTP'],',',column[@name='MSONPC'])}"/>
                    <action id="{column[@name='VRPlanId']}"/>
                </xsl:for-each>
                <xsl:for-each select="key('k', column[@name='VRPlanId'])">
                    <action id="{column[@name='VRPlanId']}"/>
                </xsl:for-each>
            </parameters>
        </Cdo>
    </xsl:if>
</xsl:template>
<xsl:template match="input"/>
</xsl:stylesheet>

大家好,

感谢您的帮助。 目标是检查我们构建标签的每个不同的 VRPlanID 值 如果它们在标签的 id 部分中不为空/空,则将相应的 MSTP、MSONPC(不同)分组。 因此,我们在 VRPlanID 之后进行分组,然后从 MSTP/MSONPC 的每条记录中获取不同的值。 如果它们是空的,那么只需构建一个虚拟/空消息/标签。 (未完成)

因此,所需的输出将是:

  <output>
   <Cdo>
     <parameters>
       <task id="22,221,2211"/>                
       <action id="1131024"/>
     </parameters>
 </Cdo>
<Cdo>
    <parameters>
       <task id="2221/>                
       <action id="999"/>
    </parameters>
 </Cdo>
  <Cdo>
    <parameters>
       <task id="33,331,222221"/>                
       <action id="11310281"/>
    </parameters>
 </Cdo>
  </output>

后期编辑:

用这个:

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

我得到了连接的结果,但不是在单独的标签中

    <parameters>
            <task id="131957513196231319667"/>
            <action id="11310281"/>
        </parameters>

【问题讨论】:

    标签: xml xslt key xslt-grouping


    【解决方案1】:

    我认为最好防止 MSTP 和 MSONPC 中的重复并将它们放入一个模板中,其中输入参数将是非重复的 VRPlanId,如下面的 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/tag/output_getquerydata/queries/query/queryResults/record[column[@name='VRPlanId'] = $param.VRPlanId]">
                    <!--preventing empty blocks and duplicates for MSTP-->          
                    <xsl:if test="string-length(column[@name='MSTP']) &gt;0 and not(preceding::record[column[@name='MSTP']/text() = current()/column[@name='MSTP']/text()])">                   
                        <xsl:value-of select="concat(column[@name='MSTP'], ',')"/>              
                    </xsl:if>                                       
                </xsl:for-each>                             
            </xsl:variable>     
            <xsl:variable name="var.msonpc">                        
                <xsl:for-each select="/output/meta2/tag/output_getquerydata/queries/query/queryResults/record[column[@name='VRPlanId'] = $param.VRPlanId]">
                    <!--preventing empty blocks and duplicates for MSONPC-->            
                    <xsl:if test="string-length(column[@name='MSONPC']) &gt;0 and not(preceding::record[column[@name='MSONPC']/text() = current()/column[@name='MSONPC']/text()])">                 
                        <xsl:value-of select="concat(column[@name='MSONPC'], ',')"/>                
                    </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/tag/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>
    

    您已经编辑了您的 XML 版本,但如果是以下 XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <output>
    <input>
        <!--details-->
    </input>
    <meta2>
        <tag>
            <output_getquerydata>
                <queries>
                    <query name="part1">
                        <parameters>
                            <!--details-->
                        </parameters>
                        <queryErrors>
                            <!--details-->
                        </queryErrors>
                        <queryResults>
                            <record id="1">                              
                                <column name="VRIdTask">1</column>                               
                                <column name="MSTP">22</column>
                                <column name="VRPlanId">11310224</column>                                
                                <column name="MSONPC">221</column> 
                            </record>
                            <record id="2">
                                <column name="VRIdTask">1</column>
                                <column name="MSTP">22</column>
                                <column name="VRPlanId">11310224</column> 
                                <column name="MSONPC">2211</column> 
                            </record>
                            <record id="3"> 
                                <column name="VRIdTask">3</column> 
                                <column name="MSTP"/>
                                <column name="VRPlanId">11310337</column> 
                                <column name="MSONPC"/> 
                            </record>
                            <record id="4"> 
                                <column name="VRIdTask">2</column> 
                                <column name="MSTP"/>
                                <column name="VRPlanId">11310281</column> 
                                <column name="MSONPC">2221</column> 
                            </record>
                            <record id="5"> 
                                <column name="VRIdTask">4</column> 
                                <column name="MSTP">33</column>
                                <column name="VRPlanId">11310281</column> 
                                <column name="MSONPC">222221</column> 
                            </record>
                            <record id="6"> 
                                <column name="VRIdTask">4</column> 
                                <column name="MSTP">331</column>
                                <column name="VRPlanId">11310281</column> 
                                <column name="MSONPC">222221</column> 
                            </record>
                        </queryResults>
                    </query>
                </queries>
            </output_getquerydata>
        </tag>
    </meta2>
    </output>
    

    结果是:

    <?xml version="1.0" encoding="UTF-8"?>
    <output>
        <Cdo>
            <parameters>
                <task id="22,221,2211"/>
                <action id="11310224"/>
            </parameters>
        </Cdo>
        <Cdo>
            <parameters>
                <task id="33,331,2221,222221"/>
                <action id="11310281"/>
            </parameters>
        </Cdo>
    </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"/>
            <tasks>
                <xsl:for-each select="/output/meta2/tag/output_getquerydata/queries/query/queryResults/record[column[@name='VRPlanId'] = $param.VRPlanId]">
                    <!--preventing empty blocks and duplicates for MSTP-->          
                    <xsl:if test="string-length(column[@name='MSTP']) &gt;0 and not(preceding::record[column[@name='MSTP']/text() = current()/column[@name='MSTP']/text()])">
                        <task>
                            <xsl:attribute name="id">
                                <xsl:value-of select="column[@name='MSTP']"/>
                            </xsl:attribute>
                        </task>                                                   
                    </xsl:if>                                       
                </xsl:for-each>
                <xsl:for-each select="/output/meta2/tag/output_getquerydata/queries/query/queryResults/record[column[@name='VRPlanId'] = $param.VRPlanId]">
                    <!--preventing empty blocks and duplicates for MSONPC-->            
                    <xsl:if test="string-length(column[@name='MSONPC']) &gt;0 and not(preceding::record[column[@name='MSONPC']/text() = current()/column[@name='MSONPC']/text()])">
                        <task>
                            <xsl:attribute name="id">                                                     
                                <xsl:value-of select="column[@name='MSONPC']"/>
                            </xsl:attribute>
                        </task>                
                    </xsl:if>                                       
                </xsl:for-each>            
            </tasks>                                                   
        </xsl:template>
    
        <xsl:template match="/">        
            <output>            
                <xsl:for-each select="/output/meta2/tag/output_getquerydata/queries/query/queryResults/record">             
                    <xsl:if test ="not(preceding::record[column[@name='VRPlanId']/text() = current()/column[@name='VRPlanId']/text()])"> 
                            <Cdo>                           
                                <parameters>                                                        
                                    <xsl:call-template name="task-attr">                                                                                                                   
                                        <xsl:with-param name="param.VRPlanId" select="column[@name='VRPlanId']"/>                                                                           
                                    </xsl:call-template>                                                             
                                    <action>                                                            
                                        <xsl:attribute name="id">                                                                           
                                            <xsl:value-of select="column[@name='VRPlanId']"/>                                                               
                                        </xsl:attribute>                                
                                    </action>                                           
                                </parameters>                       
                            </Cdo>                                                                                                                  
                    </xsl:if>           
                </xsl:for-each>                     
            </output>   
        </xsl:template>
    </xsl:stylesheet>
    

    然后当你用上面的XML检查它时,结果如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <output>
        <Cdo>
            <parameters>
                <tasks>
                    <task id="22"/>
                    <task id="221"/>
                    <task id="2211"/>
                </tasks>
                <action id="11310224"/>
            </parameters>
        </Cdo>
        <Cdo>
            <parameters>
                <tasks/>
                <action id="11310337"/>
            </parameters>
        </Cdo>
        <Cdo>
            <parameters>
                <tasks>
                    <task id="33"/>
                    <task id="331"/>
                    <task id="2221"/>
                    <task id="222221"/>
                </tasks>
                <action id="11310281"/>
            </parameters>
        </Cdo>
    </output>
    

    当然,您可以在需要的地方添加空白值验证。

    希望对您的案件有所帮助。

    【讨论】:

    • 谢谢。有效。一个问题。例如,如果我不需要连接任务 id 值,但我希望每个值都有一个单独的任务标签,这在这个 XSL 逻辑中是否可行?
    • 在这种情况下,我建议创建与“task-attr”类似的模板,并使用类似的逻辑为每个值创建所需的标签结构(例如防止重复等)。然后在 /Cdo/parameters 块中,您只需调用您创建的模板-它将获取所需的结构。请注意,您可以使用类似于“param.VRPlanId”的过滤器参数,它将收集每个 VRPlanId 的特定值。
    • 没问题,请看我的回答,我已经添加了解决方案。
    猜你喜欢
    • 2017-07-29
    • 2022-06-20
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2020-01-15
    相关资源
    最近更新 更多