Transform XML using XSLT
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&开发者_运维技巧gt;
<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>
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.
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>
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>
精彩评论