简体   繁体   中英

How to combine 2 xml to one with distinct child node using xslt

I have requirement to combine 2 xml file into single file with distinct child node in result file. I am able to combine file based on key node but child element value is not coming properly.

Please find below detail.

XML file 1-

<?xml version="1.0" encoding="UTF-8"?>
<EF_Candidate_List>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
   <name>test</name>
   <preflocation>USA</preflocation>
</EF_Candidate>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
   <name>test</name>
   <preflocation>IND</preflocation>
</EF_Candidate>
</EF_Candidate_List>

XML file 2-

<EF_Candidate_list>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
   <JobLevel>1</JobLevel>
   <jobtype>test1</jobtype>
</EF_Candidate>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
   <JobLevel>2</JobLevel>
   <jobtype>test</jobtype>
</EF_Candidate>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
   <JobLevel>3</JobLevel>
   <jobtype>test3</jobtype>
</EF_Candidate>
</EF_Candidate_list>

Expected result file

<EF_Candidate_List>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
    <name>test</name>
    <preflocation_list>
    <preflocation>IND</preflocation>
    <preflocation>USA</preflocation>
    <preflocation_list>
<profiles>
  <profile>
    <JobLevel>1</JobLevel>
    <jobtype>test1</jobtype>
  </profile>
  <profile>
    <JobLevel>2</JobLevel>
    <jobtype>test2</jobtype>
  </profile>
  <profile>
    <JobLevel>3</JobLevel>
  <jobtype>test3</jobtype>
  </profile>
</profiles>
</EF_Candidate_List>
</EF_Candidate>

I have following code

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="EF_Candidate_List">
<EF_Candidate_List xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:for-each-group select="EF_Candidate" group-by="candidate_id">
<EF_Candidate>

<xsl:variable name="current_candidate_id" select="candidate_id"/>
<xsl:variable name="JobLevel" select="document('file2.xml')/EF_Candidate_List/EF_Candidate[candidate_id = $current_candidate_id]/JobLevel" /> 
<xsl:sequence select="candidate_id" />
<name><xsl:value-of select="name"/></name>
<preflocation_list>
<xsl:for-each-group select="current-group()" group-by="preflocation">
<preflocation><xsl:value-of select="distinct-values(.)"/></preflocation>
</xsl:for-each-group>
<preflocation_list>
<JobLevel_list>
<xsl:for-each-group select="document('file2.xml')/EF_Candidate_List/EF_Candidate[candidate_id = $current_candidate_id]/JobLevel" group-by="$JobLevel">
<JobLevel><xsl:value-of select="distinct-values(.)"/></JobLevel>
</xsl:for-each-group>
</JobLevel_list>
</EF_Candidate>
</xsl:for-each-group>
</EF_Candidate_List>
</xsl:template>

current output

<EF_Candidate_List>
<EF_Candidate>
   <candidate_id>83185</candidate_id>
    <name>test</name>
<preflocation_list>
   <preflocation>IND</preflocation>
   <preflocation>USA</preflocation>
   <preflocation_list>
<JobLevels>
    <JobLevel>1</JobLevel>
    <JobLevel>1</JobLevel>
    <JobLevel>1</JobLevel>
</JobLevels>
</EF_Candidate_List>
</EF_Candidate>

I am new to xslt hence finding difficulties to trouble shoot. Any help will be much appreciated.

--- edited in response to change in question --

To get the result you show, you can do:

XSLT 2.0

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

<xsl:key name="cnd" match="EF_Candidate" use="candidate_id" />

<xsl:template match="/EF_Candidate_List">
    <xsl:copy>
        <xsl:for-each-group select="EF_Candidate" group-by="candidate_id">
            <xsl:copy>
                <xsl:copy-of select="candidate_id, name"/>
                <preflocation_list>
                    <xsl:copy-of select="current-group()/preflocation"/>
                </preflocation_list>
                <profiles>
                    <xsl:for-each select="key('cnd', candidate_id, document('file2.xml'))">
                        <profile>
                            <xsl:copy-of select="JobLevel, jobtype"/>
                        </profile>
                    </xsl:for-each> 
                </profiles>
            </xsl:copy>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

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