1

I want to transform the XML using XSLT Here is my sample XML

<EmployeList>
  <EMpDetails>
    <Name>Kiran</Name>
    <ID>ID001</ID>
    <city>Hyderabad</city>
    <Country>India</Country>
  </EMpDetails>
  <EMpDetails>
    <Name>Sunny</Name>
    <ID>ID002</ID>
    <city>Banglore</city>
    <Country>INDIA</Country>
  </EMpDetails>
  <EMpDetails>
    <Name>John</Name>
    <ID>ID001</ID>
    <city>TEXAS</city>
    <Country>US</Country>
  </EMpDetails>
  <EMpDetails>
    <Name>Raj</Name>
    <ID>ID006</ID>
    <city>Dallas</city>
    <Country>US</Country>
  </EMpDetails>
  <EMpDetails>
    <Name>Nag</Name>
    <ID>ID007</ID>
    <city>ITALY</city>
    <Country>Rome</Country>
  </EMpDetails>
</EmployeList>

Required output using XSLT

<EmployeList>
  <EMpDetails>
    <Name>Kiran</Name>
    <ID>ID001</ID>
    <city>Hyderabad</city>
    <Country>India</Country>
  </EMpDetails>
  <EMpDetails>
    <Name>Sunny</Name>
    <ID>ID002</ID>
    <city>Banglore</city>
    <Country>INDIA</Country>
  </EMpDetails>   
</EmployeList>
4
  • 1
    Could you specify your Xml with tags? Commented Jun 12, 2011 at 17:00
  • 2
    And what is the rule? Like, remove everything that is not <Country>India</Country>? Commented Jun 12, 2011 at 17:05
  • Good question, +1. See my answer for two complete solutions (for XSLT 1.0 and XSLT 2.0) that are based on the most fundamental and powerful XSLT design pattern -- the overriding of the identity rule/template. Explanation is also provided. Commented Jun 12, 2011 at 18:22
  • Should be City=Rome and Country=ITALY and not the other way around :) Commented Jun 12, 2011 at 19:34

3 Answers 3

1

Assuming that the question asks to output only EMpDetails whose Country child has a string (case-insensitive) value of "India":

I. This XSLT 1.0 transformation:

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

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

 <xsl:template match=
 "EMpDetails
    [not(translate(Country,
                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                   'abcdefghijklmnopqrstuvwxyz'
                   )
         ='india'
         )
    ]
 "/>
</xsl:stylesheet>

when applied on the provided XML document:

<EmployeList>
    <EMpDetails>
        <Name>Kiran</Name>
        <ID>ID001</ID>
        <city>Hyderabad</city>
        <Country>India</Country>
    </EMpDetails>
    <EMpDetails>
        <Name>Sunny</Name>
        <ID>ID002</ID>
        <city>Banglore</city>
        <Country>INDIA</Country>
    </EMpDetails>
    <EMpDetails>
        <Name>John</Name>
        <ID>ID001</ID>
        <city>TEXAS</city>
        <Country>US</Country>
    </EMpDetails>
    <EMpDetails>
        <Name>Raj</Name>
        <ID>ID006</ID>
        <city>Dallas</city>
        <Country>US</Country>
    </EMpDetails>
    <EMpDetails>
        <Name>Nag</Name>
        <ID>ID007</ID>
        <city>ITALY</city>
        <Country>Rome</Country>
    </EMpDetails>
</EmployeList>

produces the wanted, correct result:

<EmployeList>
   <EMpDetails>
      <Name>Kiran</Name>
      <ID>ID001</ID>
      <city>Hyderabad</city>
      <Country>India</Country>
   </EMpDetails>
   <EMpDetails>
      <Name>Sunny</Name>
      <ID>ID002</ID>
      <city>Banglore</city>
      <Country>INDIA</Country>
   </EMpDetails>
</EmployeList>

II. This XSLT 2.0 transformation:

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

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

 <xsl:template match=
 "EMpDetails[not(upper-case(Country)='INDIA')]"/>
</xsl:stylesheet>

again produces the same, wanted and correct result.

Explanation: Overriding the identity rule with a template matching all unwanted EMpDetails elements. This template has empty body, which effectively prevents copying any such matched elements to the output.

Remember: Using and overriding the identity rule/template is the most fundamental and most powerful XSLT design pattern.

Sign up to request clarification or add additional context in comments.

3 Comments

If 'india' is fixed, not(translate(Country, 'INDA', 'inda') = 'india') would probably be more efficient.
HI Thanks for the reply and solution. can you provide me any docs to get more XSLT
0

That should work as you need (assuming that you want all EMpDetails elements where Country is equal to India with case-insensitivity):

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

    <xsl:template match="EmployeList">
        <EmployeList>
            <xsl:copy-of select="EMpDetails[lower-case(Country) = 'india']"/>
        </EmployeList>
    </xsl:template>
</xsl:stylesheet>

5 Comments

There is a small problem in your solution -- a wrong and misleading version attribute that would lead people to believe they can use this with an XSLT 1.0 processor. Please, correct.
Thanks to @empo for editing the answer and correcting the version. I am still not deleting my comment so that the original author confirms he has seen it and will know not to make such mistakes in the future.
@Dimitre Novatchev, @empo: Thanks for correcting. lower-case() function is available in XPath 2.0 (strange that Oxygen XML didn't complain about that..). For 1.0 version translate() function made the job.
HI Thanks for the reply and solution can you provide me the any docs on XML to XML transformation using XSLT
@kiran425: At beginning you can start with W3schools XML Tutorials (w3schools.com): (Learn XML), Learn XPath, Learn XSLT (in practice you can't write XSLT without knowing XPath). There aren't fully comprehensive, but easy to learn.
0

Assuming your sample input is simple as it's shown you could also go with:

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

    <xsl:template match="/EmployeList">
        <xsl:copy>
            <xsl:copy-of select="EMpDetails[
                Country[
                .='India'
                or .='INDIA']
                ]"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

1 Comment

Hi,Thanks for the reply and solution can send me any link or documents to study more on XSLT

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.