简体   繁体   中英

XSLT transform with repeating elements and parent node

I am trying to transform the below xml to rows and columns. The Job_Classification_Group can have many child Job_Classifications . I need the Job_Classification_Group_ID to come first in all of the rows, then the information about that Job_Classification_Group , and then each Job_Classification_Reference_ID

In other words:

Job_Classification_Group_ID|wd:ID|wd:Effective_Date|wd:Job_Classification_Group_Name|wd:Location_Reference[2]|wd:Location_Reference[3]|wd:Location_Reference[4]|wd:Job_Classification_Data/Job_Classification_Reference_ID[1] Job_Classification_Group_ID|wd:ID|wd:Effective_Date|wd:Job_Classification_Group_Name|wd:Location_Reference[2]|wd:Location_Reference[3]|wd:Location_Reference[4]|wd:Job_Classification_Data/Job_Classification_Reference_ID[2]

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Body>
      <wd:Get_Job_Classification_Groups_Response wd:version="v29.1" xmlns:wd="urn:com.workday/bsvc">
         <wd:Response_Filter>
            <wd:Page>3</wd:Page>
            <wd:Count>1</wd:Count>
         </wd:Response_Filter>
         <wd:Response_Group>
            <wd:Include_Reference>1</wd:Include_Reference>
            <wd:Include_Job_Classifications>1</wd:Include_Job_Classifications>
         </wd:Response_Group>
         <wd:Response_Results>
            <wd:Total_Results>21</wd:Total_Results>
            <wd:Total_Pages>21</wd:Total_Pages>
            <wd:Page_Results>1</wd:Page_Results>
            <wd:Page>3</wd:Page>
         </wd:Response_Results>
         <wd:Response_Data>
            <wd:Job_Classification_Group>
               <wd:Job_Classification_Group_Reference wd:Descriptor="Klassifikation der Berufe 2010 (KldB 2010)">
                  <wd:ID wd:type="WID">16d569ce573c01b6725820441e3b7049</wd:ID>
                  <wd:ID wd:type="Job_Classification_Group_ID">KldB2010_Germany</wd:ID>
               </wd:Job_Classification_Group_Reference>
               <wd:Job_Classification_Group_Name_Data>
                  <wd:Job_Classification_Group_Name>Klassifikation der Berufe 2010 (KldB 2010)</wd:Job_Classification_Group_Name>
               </wd:Job_Classification_Group_Name_Data>
               <wd:Job_Classification_Group_Data>
                  <wd:ID>KldB2010_Germany</wd:ID>
                  <wd:Effective_Date>2018-04-18-07:00</wd:Effective_Date>
                  <wd:Job_Classification_Group_Name>Klassifikation der Berufe 2010 (KldB 2010)</wd:Job_Classification_Group_Name>
                  <wd:Location_Reference wd:Descriptor="Germany">
                     <wd:ID wd:type="WID">dcc5b7608d8644b3a93716604e78e995</wd:ID>
                     <wd:ID wd:type="ISO_3166-1_Alpha-2_Code">DE</wd:ID>
                     <wd:ID wd:type="ISO_3166-1_Alpha-3_Code">DEU</wd:ID>
                     <wd:ID wd:type="ISO_3166-1_Numeric-3_Code">276</wd:ID>
                  </wd:Location_Reference>
                  <wd:Inactive>0</wd:Inactive>
                  <wd:Job_Classification>
                     <wd:Job_Classification_Reference wd:Descriptor="1 - Land-, Forst- und Tierwirtschaft und Gartenbau (Klassifikation der Berufe 2010 (KldB 2010)-Germany)">
                        <wd:ID wd:type="WID">16d569ce573c0159e47b20441e3b7149</wd:ID>
                        <wd:ID wd:type="Job_Classification_Reference_ID">KldB2010_Germany_1_Land-,_Forst-_und_Tierwirtschaft_und_Gartenbau</wd:ID>
                     </wd:Job_Classification_Reference>
                     <wd:Job_Classification_Data>
                        <wd:ID>KldB2010_Germany_1_Land-,_Forst-_und_Tierwirtschaft_und_Gartenbau</wd:ID>
                        <wd:Job_Classification_ID>1</wd:Job_Classification_ID>
                        <wd:Description>Land-, Forst- und Tierwirtschaft und Gartenbau</wd:Description>
                        <wd:Inactive>0</wd:Inactive>
                     </wd:Job_Classification_Data>
                  </wd:Job_Classification>
                  <wd:Job_Classification>
                     <wd:Job_Classification_Reference wd:Descriptor="11 - Land-, Tier- und Forstwirtschaftsberufe (Klassifikation der Berufe 2010 (KldB 2010)-Germany)">
                        <wd:ID wd:type="WID">16d569ce573c016e488520441e3b7249</wd:ID>
                        <wd:ID wd:type="Job_Classification_Reference_ID">KldB2010_Germany_11_Land-,_Tier-_und_Forstwirtschaftsberufe</wd:ID>
                     </wd:Job_Classification_Reference>
                     <wd:Job_Classification_Data>
                        <wd:ID>KldB2010_Germany_11_Land-,_Tier-_und_Forstwirtschaftsberufe</wd:ID>
                        <wd:Job_Classification_ID>11</wd:Job_Classification_ID>
                        <wd:Description>Land-, Tier- und Forstwirtschaftsberufe</wd:Description>
                        <wd:Inactive>0</wd:Inactive>
                     </wd:Job_Classification_Data>
                  </wd:Job_Classification>
               </wd:Job_Classification_Group_Data>
            </wd:Job_Classification_Group>
         </wd:Response_Data>
      </wd:Get_Job_Classification_Groups_Response>
   </env:Body>
</env:Envelope>

I have a simple XSLT to build this without the Job_Classification_Reference_ID

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wd="urn:com.workday/bsvc" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:variable name="newline">
        <xsl:text>&#166;</xsl:text>
    </xsl:variable>
    <xsl:variable name="comma">
        <xsl:text>&#44;</xsl:text>
    </xsl:variable>
    <xsl:variable name="quote">
        <xsl:text>&#39;</xsl:text>
    </xsl:variable>
    <xsl:variable name="rs">
        <xsl:text>&#124;</xsl:text>
    </xsl:variable>
    <xsl:template match="/">
        <xsl:apply-templates select="/env:Envelope/env:Body/wd:Get_Job_Classification_Groups_Response/wd:Response_Data"/>
    </xsl:template>
    <xsl:template match="/env:Envelope/env:Body/wd:Get_Job_Classification_Groups_Response/wd:Response_Data">
        <xsl:for-each select="wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Job_Classification/wd:Job_Classification_Reference/wd:ID[2]">
            <xsl:value-of select="../../../wd:ID"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Effective_Date"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Job_Classification_Group_Name"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Inactive"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Location_Reference/wd:ID[2]"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Location_Reference/wd:ID[3]"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="../../../wd:Location_Reference/wd:ID[4]"/>
            <xsl:value-of select="$rs"/>
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
                <xsl:value-of select="$newline"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Which outputs:

KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_1_Land-,_Forst-_und_Tierwirtschaft_und_Gartenbau¦KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_11_Land-,_Tier-_und_Forstwirtschaftsberufe

Which is close, but does not have Job_Classification_Group_ID

I cannot figure out how to keep the repeating Job_Classification_Reference_ID while also adding the Job_Classification_Group_ID . I tried creating another template which was called from inside the loop but got an error (Using XMLSpy). That template would just output the Job_Classification_Reference_ID value.

EDIT: Expected output

KldB2010_Germany|KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_1_Land-,_Forst-_und_Tierwirtschaft_und_Gartenbau¦
KldB2010_Germany|KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_11_Land-,_Tier-_und_Forstwirtschaftsberufe

But the first column is Job_Classification_Group_ID from wd:Job_Classification_Group_Reference . Not wd:Job_Classification_Group_Data . That is the 2nd column

There are couple of suggestions to achieve the desired output. The requirement is to get the value of

<xsl:value-of select="wd:Job_Classification_Reference/wd:ID[@wd:type='Job_Classification_Reference_ID']"/>

on separate rows in the output text. In order to do it the <xsl:for-each> should run on <wd:Job_Classification> instead of wd:Job_Classification/wd:Job_Classification_Reference/wd:ID[2] .

Secondly, in this particular scenario, instead of using ../../../ to go up levels for accessing parent node values, a better way is to use ancestor:: axis which will help in easily creating the XPath and navigating to the required node. It also helps in understanding which element value is being accessed by just looking at the XSLT code.

Thirdly, instead of accessing values using wd:ID[2] , wd:ID[3] , wd:ID[4] it would be good to access them using the @wd:type attribute value ie wd:ID[@wd:type='ISO_3166-1_Alpha-2_Code'] and so on for the others. This will ensure the output does not change even if the sequence of the wd:ID elements in the input change.

Based on the above suggestions the wd:ResponseData template is modified as below.

<xsl:template match="/env:Envelope/env:Body/wd:Get_Job_Classification_Groups_Response/wd:Response_Data">
    <xsl:for-each select="wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Job_Classification">
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Reference/wd:ID[@wd:type='Job_Classification_Group_ID']" />
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:ID" />
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Effective_Date"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Job_Classification_Group_Name"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Inactive"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Location_Reference/wd:ID[@wd:type='ISO_3166-1_Alpha-2_Code']"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Location_Reference/wd:ID[@wd:type='ISO_3166-1_Alpha-3_Code']"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="ancestor::wd:Job_Classification_Group/wd:Job_Classification_Group_Data/wd:Location_Reference/wd:ID[@wd:type='ISO_3166-1_Numeric-3_Code']"/>
        <xsl:value-of select="$rs"/>
        <xsl:value-of select="wd:Job_Classification_Reference/wd:ID[@wd:type='Job_Classification_Reference_ID']"/>
        <xsl:if test="position() != last()">
            <xsl:value-of select="$newline"/>
            <xsl:text>&#xA;</xsl:text>
        </xsl:if> 
    </xsl:for-each>
</xsl:template>

This will generate the required output

KldB2010_Germany|KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_1_Land-,_Forst-_und_Tierwirtschaft_und_Gartenbau¦
KldB2010_Germany|KldB2010_Germany|2018-04-18-07:00|Klassifikation der Berufe 2010 (KldB 2010)|0|DE|DEU|276|KldB2010_Germany_11_Land-,_Tier-_und_Forstwirtschaftsberufe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM