XSLT-группа по переменной

ВХОД:

  <?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, которое мы создаем для тега. Сгруппировать соответствующие MSTP, MSONPC (различные), если они не являются нулевыми/пустыми в части идентификатора тега. Итак, мы группируем после VRPlanID, затем получаем отдельные значения из каждой записи из MSTP/MSONPC. Если они пусты, просто создайте фиктивное/нулевое сообщение/тег. Это работает, но у меня есть 2 проблемы: - я всегда получаю запятую после последнего идентификатора, и я не могу понять, почему - мне больше не нужен конкатенированный, но я хочу иметь задачу тега для каждого идентификатора

Итак, желаемый результат будет:

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

Имейте в виду, что возможна любая комбинация тегов MSSinergieTaskP и MSSinergieTaskNP. Так что один может быть пустым, другой нет. Или один пустой только для записи, чтобы следующая запись имела значение. Мне просто интересно получить разные значения для любой комбинации, для них обоих, для каждой отдельной VRIdTask.

Кажется, я не могу заставить это работать. Любые предложения, пожалуйста?


person user3529643    schedule 12.12.2017    source источник
comment
Вы проверили muenchian grouping? Кажется, это проблема, которую можно решить с помощью muenchian grouping, используя составной key, созданный с использованием @MSSinergieTaskP и @MSSinergieTaskNP.   -  person Aniket V    schedule 13.12.2017
comment
ну да, xsl работает для большинства частей, но я не могу понять, как изменить вывод по желанию, это должно быть проблемой структуры шаблона, но я не нашел решения :(   -  person user3529643    schedule 13.12.2017
comment
Пожалуйста, посмотрите ответ ниже: условие выполнено">stackoverflow.com/questions/47764901/   -  person Alex Fomin    schedule 13.12.2017


Ответы (1)


Для группировки в XSLT 1.0 наиболее эффективным решением является использование мюнхенской группировки.

В этом сценарии вы можете создать ключ группировки, используя значение в атрибуте @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 проверьте, имеют ли какие-либо из MSSinergieTaskP или MSSinergieTaskNP значения, а затем выполните цикл по сгруппированным узлам, чтобы получить значения из 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>
person Aniket V    schedule 13.12.2017