1

I have the following XML:

<EMPLOYEE_LIST>
    <EMPLOYEES_01>
        <PERMANENT>
            <EMPID>650000</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>H</MIDDLE_NAME>
            <LAST_NAME>ROGERS</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650001</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>Y</MIDDLE_NAME>
            <LAST_NAME>HANNAH</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_01>
    <EMPLOYEES_02>
        <PERMANENT>
            <EMPID>650002</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>ROGERS</MIDDLE_NAME>
            <LAST_NAME>H</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650003</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>HANNAH</MIDDLE_NAME>
            <LAST_NAME>Y</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_02>
</EMPLOYEE_LIST>

And I am using the following XML to transform it:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/EMPLOYEE_LIST">
        <employees>
            <xsl:apply-templates select="EMPLOYEES/node()"/>
        </employees>        
    </xsl:template>    
    <xsl:template match="PERMANENT">
        <permanent>
            <xsl:apply-templates select="*"/>
        </permanent>
    </xsl:template>    
    <xsl:template match="EMPID">
        <emp_id>
            <xsl:value-of select="."/>
        </emp_id>
    </xsl:template>    
    <xsl:template match="FIRST_NAME">
        <f_name>
            <xsl:value-of select="."/>
        </f_name>
    </xsl:template>    
    <xsl:template match="MIDDLE_NAME">
        <m_name>
            <xsl:value-of select="."/>
        </m_name>
    </xsl:template>    
    <xsl:template match="LAST_NAME">
        <l_name>
            <xsl:value-of select="."/>
        </l_name>
    </xsl:template>

    <xsl:template match="CONTRACTUAL">
        <permanent>
            <xsl:apply-templates select="*"/>
        </permanent>
    </xsl:template>    
    <xsl:template match="EMPID">
        <emp_id>
            <xsl:value-of select="."/>
        </emp_id>
    </xsl:template>    
    <xsl:template match="FIRST_NAME">
        <f_name>
            <xsl:value-of select="."/>
        </f_name>
    </xsl:template>    
    <xsl:template match="MIDDLE_NAME">
        <m_name>
            <xsl:value-of select="."/>
        </m_name>
    </xsl:template>    
    <xsl:template match="LAST_NAME">
        <l_name>
            <xsl:value-of select="."/>
        </l_name>
    </xsl:template>
</xsl:stylesheet>

Expecting the converted XML with the following output:

<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee>
        <emp_id>650000</emp_id>
        <f_name>KEITH</f_name>
        <m_name>H</m_name>
        <l_name>ROGERS</l_name>
        <type>permanent</type>
        <emp_id>650001</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>Y</m_name>
        <l_name>HANNAH</l_name>
        <type>contractual</type>
        <emp_id>650002</emp_id>
        <f_name>KEITH</f_name>
        <m_name>ROGERS</m_name>
        <l_name>H</l_name>
        <type>permanent</type>
        <emp_id>650003</emp_id>
        <f_name>DARRYL</f_name>
        <m_name>HANNAH</m_name>
        <l_name>Y</l_name>
        <type>contractual</type>
    </employee>
</employees>

so far i haven't been successful at it as i am new to this and any help would be appreciated

thanks

2 Answers2

1

I'll use Dimitre's answer to your previous question as a base here since it was more concise than mine:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <my:Renames>
    <n old="EMPLOYEES" new="employees"/>
    <n old="EMPID" new="emp_id"/>
    <n old="FIRST_NAME" new="f_name"/>
    <n old="MIDDLE_NAME" new="m_name"/>
    <n old="LAST_NAME" new="l_name"/>
    <n old="PERMANENT" new="permanent"/>
    <n old="CONTRACTUAL" new="contractual"/>
  </my:Renames>

  <xsl:variable name="vRenames" select="document('')/*/my:Renames/*"/>

  <xsl:template match="EMPLOYEE_LIST">
    <employees>
      <employee>
        <xsl:apply-templates select="*/*" />
      </employee>
    </employees>
  </xsl:template>

  <xsl:template match="*/*" priority="-1">
    <xsl:element name="{$vRenames[@old = name(current())]/@new}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="PERMANENT|CONTRACTUAL">
    <xsl:apply-templates/>
    <type>
      <xsl:value-of select="$vRenames[@old = name(current())]/@new"/>
    </type>
  </xsl:template>
</xsl:stylesheet>

The new part is this:

  <xsl:template match="EMPLOYEE_LIST">
    <employees>
      <employee>
        <xsl:apply-templates select="*/*" />
      </employee>
    </employees>
  </xsl:template>

When run on your sample input from above, this produces:

<employees>
  <employee>
    <emp_id>650000</emp_id>
    <f_name>KEITH</f_name>
    <m_name>H</m_name>
    <l_name>ROGERS</l_name>
    <type>permanent</type>
    <emp_id>650001</emp_id>
    <f_name>DARRYL</f_name>
    <m_name>Y</m_name>
    <l_name>HANNAH</l_name>
    <type>contractual</type>
    <emp_id>650002</emp_id>
    <f_name>KEITH</f_name>
    <m_name>ROGERS</m_name>
    <l_name>H</l_name>
    <type>permanent</type>
    <emp_id>650003</emp_id>
    <f_name>DARRYL</f_name>
    <m_name>HANNAH</m_name>
    <l_name>Y</l_name>
    <type>contractual</type>
  </employee>
</employees>
JLRishe
  • 99,490
  • 19
  • 131
  • 169
1

A shorter and more "push-style" solution: Just adapt slightly my answer to the previous question:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:Renames>
  <n old="EMPID" new="emp_id"/>
  <n old="FIRST_NAME" new="f_name"/>
  <n old="MIDDLE_NAME" new="m_name"/>
  <n old="LAST_NAME" new="l_name"/>
  <n old="PERMANENT" new="permanent"/>
  <n old="CONTRACTUAL" new="contractual"/>
 </my:Renames>

 <xsl:variable name="vRenames" select="document('')/*/my:Renames/*"/>

 <xsl:template match="EMPLOYEE_LIST">
  <employees><employee><xsl:apply-templates/></employee></employees>
 </xsl:template>

 <xsl:template match="*/*/*" priority="-1">
     <xsl:element name="{$vRenames[@old = name(current())]/@new}">
       <xsl:apply-templates/>
     </xsl:element>
 </xsl:template>

 <xsl:template match="PERMANENT|CONTRACTUAL">
  <xsl:apply-templates/>
  <type><xsl:value-of select="$vRenames[@old = name(current())]/@new"/></type>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied to the provided XML document:

<EMPLOYEE_LIST>
    <EMPLOYEES_01>
        <PERMANENT>
            <EMPID>650000</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>H</MIDDLE_NAME>
            <LAST_NAME>ROGERS</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650001</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>Y</MIDDLE_NAME>
            <LAST_NAME>HANNAH</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_01>
    <EMPLOYEES_02>
        <PERMANENT>
            <EMPID>650002</EMPID>
            <FIRST_NAME>KEITH</FIRST_NAME>
            <MIDDLE_NAME>ROGERS</MIDDLE_NAME>
            <LAST_NAME>H</LAST_NAME>
        </PERMANENT>
        <CONTRACTUAL>
            <EMPID>650003</EMPID>
            <FIRST_NAME>DARRYL</FIRST_NAME>
            <MIDDLE_NAME>HANNAH</MIDDLE_NAME>
            <LAST_NAME>Y</LAST_NAME>
        </CONTRACTUAL>
    </EMPLOYEES_02>
</EMPLOYEE_LIST>

the wanted, correct result is produced:

<employees>
   <employee>
      <emp_id>650000</emp_id>
      <f_name>KEITH</f_name>
      <m_name>H</m_name>
      <l_name>ROGERS</l_name>
      <type>permanent</type>
      <emp_id>650001</emp_id>
      <f_name>DARRYL</f_name>
      <m_name>Y</m_name>
      <l_name>HANNAH</l_name>
      <type>contractual</type>
      <emp_id>650002</emp_id>
      <f_name>KEITH</f_name>
      <m_name>ROGERS</m_name>
      <l_name>H</l_name>
      <type>permanent</type>
      <emp_id>650003</emp_id>
      <f_name>DARRYL</f_name>
      <m_name>HANNAH</m_name>
      <l_name>Y</l_name>
      <type>contractual</type>
   </employee>
</employees>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • would your suggestion work if I modify the parent node name from EMPLOYEES_02 to ESTRANGED_02? – Reggie Miller Mar 02 '13 at 19:53
  • @ReggieMiller, Yes, just try it :) – Dimitre Novatchev Mar 02 '13 at 19:59
  • haven't tried it with the entire XML but can you tell me if there is a way to truncate/leave out unwanted elements during transformation? say i'd like to truncate l_name during transformation so that the resulting xml has only f_name/m_name?can that be done within this code? – Reggie Miller Mar 02 '13 at 20:48
  • @ReggieMiller, Sure can, but this is yet another new question :) See my answer to this question: http://stackoverflow.com/questions/321860/how-to-remove-elements-from-xml-using-xslt-with-stylesheet-and-xsltproc/322079#322079 – Dimitre Novatchev Mar 02 '13 at 21:13