0

I don't have any experience to create xslt transformers. please some one can help me to to transform bellow xml?

<Top>
   <cod>a<cod>
   <types>
       <type> 
           <start>2018-05-24</start>
           <end>2019-01-24</end>
           <empl>Ext</empl> 
       <type>
       <type> 
           <start>2019-01-25</start>
           <end>9999-12-31</end>
           <empl>Int</empl> 
       <type>  
   </types>
   <lent>10</lent> 
   <tree>asd</tree> 
</Top>

I need to transform it to get only latest empl type;

<Top>
    <cod>a<cod>
    <empl>Int</empl> 
    <lent>10</lent> 
   <tree>asd</tree> 
</Top>

1 Answers1

0

First, make sure that your XML is well-formed like this:

<Top>
   <cod>a</cod>
   <types>
       <type> 
           <start>2018-05-24</start>
           <end>2019-01-24</end>
           <empl>Ext</empl> 
       </type>
       <type> 
           <start>2019-01-25</start>
           <end>9999-12-31</end>
           <empl>Int</empl> 
       </type>  
   </types>
   <lent>10</lent> 
   <tree>asd</tree> 
</Top>

Then simply combine the identity template with a copy-of template:

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

    <!-- identity template - copies all nodes -->
    <xsl:template match="node()|@*">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
    </xsl:template>  

    <!-- Remove 'types' element and its children except for one 'empl' node -->
    <xsl:template match="types">
        <xsl:copy-of select="type[2]/empl" />
    </xsl:template>

</xsl:stylesheet>

If you want to copy both <empl> elements, remove the [2] from the expression.

It's output is:

<Top>
    <cod>a</cod>
    <empl>Int</empl>
    <lent>10</lent>
    <tree>asd</tree>
</Top>
zx485
  • 28,498
  • 28
  • 50
  • 59
  • can we get the value of "empl" only if it is valued for today? (If the current date is between start and end ) – L. A. U. Shamantha May 29 '19 at 11:12
  • You can use the XSLT-2.0 function [`current-date()`](http://www.xsltfunctions.com/xsl/fn_current-date.html) or the ExSLT extension like described in [this answer](https://stackoverflow.com/a/1575134/1305969). Using XSLT-2.0, replace the `type[2]/empl` expression with `type[substring(translate(current-date(),'-',''),1,8) > translate(start,'-','') and translate(end,'-','') > substring(translate(current-date(),'-',''),1,8)]/empl`. – zx485 May 29 '19 at 16:35
  • This may not be the most elegant XSLT-2.0 solution, but it could also be used in an ExSLT approach. – zx485 May 29 '19 at 16:41
  • IT is very helpful but still I have an issue with some of xml inpits. for a example if root tab contain namespace and other attributes this solution didn't work. I got some time as bellow – L. A. U. Shamantha May 31 '19 at 12:22
  • The namespace defined like this is inherited by all children. So you have to add the prefix in the XPath expressions as well. For example, add a prefixed namespace to the stylesheet element like this `xmlns:ifs="urn:ifsworld-com:schemas:employee_interaction_send_employee_request"` and then change the template to ` `. – zx485 May 31 '19 at 13:41