Search code examples
xsltxslt-2.0

How to get two same level node values based on a condition using XSLT?


I am new to XSLT code and need your help. I am building a report using XML and need to transform the XML for required fields but based on a condition between two nodes. I have almost completed the logic, but for one of the records my logic is not working because of multiple same nodes.

From the below xml output: I need to match the Worker_Events_Complete_Group -> EffectiveDate with Job_History_group Effective date and display the fields only when it is matching.

<Report_Entry>
<Employee_ID>50067</Employee_ID>
<Worker>John Grisolano</Worker>
<Worker_Events_Completed_group>
    <EffectiveDate>2019-01-01</EffectiveDate>
    <DateTimeCompleted>2019-01-09T14:23:06.679-08:00</DateTimeCompleted>
    <Business_Process_Type>Transfer Employee</Business_Process_Type>
</Worker_Events_Completed_group>
<Worker_Events_Completed_group>
    <EffectiveDate>2019-04-01</EffectiveDate>
    <DateTimeCompleted>2019-04-03T07:53:43.965-07:00</DateTimeCompleted>
    <Business_Process_Type>Transfer Employee</Business_Process_Type>
</Worker_Events_Completed_group>
<Job_History_group>
    <Effective_Date>2019-01-01</Effective_Date>
    <Class_of_Instance>Position Snapshot</Class_of_Instance>
    <Scheduled_Weekly_Hours>40</Scheduled_Weekly_Hours>
    <Default_Weekly_Hours>40</Default_Weekly_Hours>
</Job_History_group>
<Job_History_group>
    <Effective_Date>2019-04-01</Effective_Date>
    <Class_of_Instance>Position Snapshot</Class_of_Instance>
    <Scheduled_Weekly_Hours>40</Scheduled_Weekly_Hours>
    <Default_Weekly_Hours>40</Default_Weekly_Hours>
</Job_History_group>
</Report_Entry>

XSLT code I used is as below: but this is failing because of the same level nodes, it was not able to go inside Job_History_Group.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
    <ChangeEvent>
        <EmpID><xsl:value-of select="Report_Entry/Employee_ID"/></EmpID>
        <xsl:variable name="Current_Date" select="Report_Entry/Worker_Events_Completed_group/EffectiveDate"/>
        <EventDetails>
            <xsl:for-each select="Report_Entry/Worker_Events_Completed_group">
                <Event>
                    <ChangeEventDate><xsl:value-of select="EffectiveDate"/></ChangeEventDate>
                    <ChangeEntryDate><xsl:value-of select="DateTimeCompleted"/></ChangeEntryDate>
                    <ChangeType><xsl:value-of select="CF_Census_Change_Type"/></ChangeType> 
                    <FTE_Snapshot>
                        <xsl:for-each select="Job_History_group">
                            <Snapshot>
                                <xsl:choose> 
                                    <xsl:when test="$Current_Date = Effective_Date">
                                        <xsl:variable name="swh" select="Scheduled_Weekly_Hours"/>
                                        <xsl:variable name="dwh" select="Default_Weekly_Hours"/>
                                        <Snapshot_EffectiveDate><xsl:value-of select="Effective_Date"/></Snapshot_EffectiveDate>
                                        <Snapshot_FTE><xsl:value-of select="$swh div $dwh * 100"/></Snapshot_FTE>
                                    </xsl:when>
                                    <xsl:otherwise/>
                                </xsl:choose>
                            </Snapshot>
                        </xsl:for-each>
                    </FTE_Snapshot>
                </Event>

            </xsl:for-each> 
        </EventDetails>
    </ChangeEvent>
   </xsl:template>
</xsl:stylesheet>

Expected output is as below:

<?xml version="1.0" encoding="UTF-8"?>
<ChangeEvent >
<EmpID>50067</EmpID>
<EventDetails>
    <Event>
        <ChangeEventDate>2019-01-01</ChangeEventDate>
        <ChangeEntryDate>2019-01-09T14:23:06.679-08:00</ChangeEntryDate>
        <ChangeType>Cost Center</ChangeType>
        <FTE_Snapshot>
            <Snapshot>   
                <Effective_Date>2019-01-01</Effective_Date>
                <Class_of_Instance>Position Snapshot</Class_of_Instance>
                <Scheduled_Weekly_Hours>40</Scheduled_Weekly_Hours>
                <Default_Weekly_Hours>40</Default_Weekly_Hours>
            </Snapshot>
        </FTE_Snapshot>
    </Event>
    <Event>
        <ChangeEventDate>2019-04-01</ChangeEventDate>
        <ChangeEntryDate>2019-04-03T07:53:43.965-07:00</ChangeEntryDate>
        <ChangeType>Cost Center</ChangeType>
        <FTE_Snapshot>
          <Snapshot>
            <Effective_Date>2019-04-01</Effective_Date>
            <Class_of_Instance>Position Snapshot</Class_of_Instance>
            <Scheduled_Weekly_Hours>40</Scheduled_Weekly_Hours>
            <Default_Weekly_Hours>40</Default_Weekly_Hours>
          <Snapshot>
        </FTE_Snapshot>
       </Event>
    </EventDetails>
</ChangeEvent>

Solution

  • I think that you're almost there! I moved Current_Date to within each Worker_Events_Completed_group, added ../ to select the sibling node, and then filtered the Job_History_group based on the match that you hint at in your conditional:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xsl:output indent="yes" />
        <xsl:template match="/">
            <ChangeEvent>
                <EmpID><xsl:value-of select="Report_Entry/Employee_ID"/></EmpID>           
                <EventDetails>
                  <xsl:for-each select="Report_Entry/Worker_Events_Completed_group">
                      <xsl:variable name="Current_Date" select="EffectiveDate"/>
                      <Event>
                          <ChangeEventDate><xsl:value-of select="EffectiveDate"/></ChangeEventDate>
                          <ChangeEntryDate><xsl:value-of select="DateTimeCompleted"/></ChangeEntryDate>
                          <ChangeType><xsl:value-of select="CF_Census_Change_Type"/></ChangeType> 
                          <FTE_Snapshot>  
                              <xsl:for-each select="../Job_History_group[Effective_Date=$Current_Date]">
                                  <Snapshot>
                                      <xsl:variable name="swh" select="Scheduled_Weekly_Hours"/>
                                      <xsl:variable name="dwh" select="Default_Weekly_Hours"/>
                                      <Snapshot_EffectiveDate><xsl:value-of select="Effective_Date"/></Snapshot_EffectiveDate>
                                      <Snapshot_FTE><xsl:value-of select="$swh div $dwh * 100"/></Snapshot_FTE>
                                  </Snapshot>
                              </xsl:for-each>
                          </FTE_Snapshot>
                      </Event>
                      </xsl:for-each>                   
                </EventDetails>
            </ChangeEvent>
        </xsl:template>
    </xsl:stylesheet>