Tuesday, July 19, 2011

Calling Java Methods From XSL While XML Transformation

In my earlier article, I have shown you how to transform a XML from one format to another format.
Below, I will show you how to refer to a Java class from an XSL.

This is the java class which I want to refer to the xsl file. And getDemoProperties() is the method name which I will call from XSL. This is nothing but to get a properties flag value from the properties file.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;


public class DemoProperties {
                 Properties props;
               static String fName = "./DemoProperties.properties";
                   
                    public DemoProperties() {
                        props = new Properties();
                        try {
                                props.load(new FileInputStream(fName));
                        } catch (FileNotFoundException fnfEx){
                                                                fnfEx.printStackTrace();
                        }
                        catch (IOException ioEx){
                            ioEx.printStackTrace();
                        }
                    }
                   
                   
                   
     public String getDemoProperties(String propName) {
                        String retProp=new String("");
                        try {
                            retProp = props.getProperty(propName);
                        } catch(Exception e) {
                                                                e.printStackTrace();
                        }
                        return retProp;
                    }
}

DemoProperties.properties entry.

id=ID1


Input XML file:

       <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
       <Order>
         <CustomerID>0123456789</CustomerID>
         <Title>Mr</Title>
         <FirstName>Vicky</FirstName>
         <Initial>VV</Initial>
         <Surname>Verma</Surname>
         <TelephoneNumber>0987654321</TelephoneNumber>
         <SubPremise>RakhsakNagar</SubPremise>
         <BuildingName>RakhsakNagar</BuildingName>
         <StreetNumber>207</StreetNumber>
         <StreetName>KharadiByPass</StreetName>
         <Locality>Kharadi</Locality>
         <PostTown>Pune</PostTown>
         <County>Pune</County>
         <Postcode>411014</Postcode>
         <OrderDate>20052009 15:18:11</OrderDate>
         <CADDate>05062009 15:23:54</CADDate>
         <OrderReference>022-123456789</OrderReference>
         <DealerChannel>Airtel Voice</DealerChannel>
         <InstallationType>Self</InstallationType>
         <AssetDescription>Airtel TV</AssetDescription>
         <Action>Add</Action>
         <ReplacementType>Active</ReplacementType>
         <CurrentDate>20090611T11:15:08</CurrentDate>
  </Order>



Sample XSL file:
       <?xml version="1.0" encoding="UTF-8" ?>
       <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rf="DemoProperties">
         <xsl:strip-space elements="*" />
         <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes" />
       <xsl:template match="Order">
       <OrderForProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <xsl:variable name="props" select="rf:new()" />
       <xsl:variable name="var">
         <xsl:value-of select="rf:getCPSProperties($props, 'id')" />
  </xsl:variable>
       <UniqueKey>
       <xsl:attribute name="Id">
         <xsl:value-of select="$var" />
  </xsl:attribute>
         </UniqueKey>
       <ProductsDetails>
         <Product Name="Airtel_TV" />
  </ProductsDetails>
       <PriorSubmission>
         <xsl:attribute name="UserName">AirtelUser</xsl:attribute>
       <xsl:attribute name="SubmitterRef">
         <xsl:value-of select="OrderReference" />
  </xsl:attribute>
  </PriorSubmission>
  </OrderForProduct>
  </xsl:template>
  </xsl:stylesheet>


XMLTransformation.java – Java class which actually does the transformation

import java.io.File;
import java.io.FileOutputStream;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;


public class XMLTransformation {


                XMLTransformation() {

                }
               

                private static void applyTransformAndSave() {
                                 try {
                                                                String sampleInputXML= "SampleInputXML.xml";
                            File sampleInputFile = new File(sampleInputXML);
                                        String sampleOutputXML = "SampleOutputFile.xml";
                            //Convert input file to output batch file according to the XSL
                                        TransformerFactory tFactory1 = TransformerFactory.newInstance();
                                                    Transformer transformer1;
                                                                transformer1 = tFactory1.newTransformer(new StreamSource("SampleXSL.xsl"));
                                                                transformer1.setOutputProperty(OutputKeys.INDENT, "yes");
                            transformer1.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
                                                    transformer1.transform(new StreamSource(sampleInputFile), new StreamResult(new FileOutputStream(sampleOutputXML)));
                                                } catch (TransformerConfigurationException tCEx){
                                                                tCEx.printStackTrace();
                        } catch (TransformerException tEx){
                                                                tEx.printStackTrace();
                                                } catch(Exception ex){
                                                                ex.printStackTrace();
                        }
    }



                public static void main(String args[]) {
                                                XMLTransformation xmlTransformation = new XMLTransformation();
                                                XMLTransformation.applyTransformAndSave();
                }

}


Output XML file:

       <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
       <OrderForProduct xmlns:rf="DemoProperties"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <UniqueKey Id="ID1" />
       <ProductsDetails>
         <Product Name="Airtel_TV" />
  </ProductsDetails>
        <PriorSubmission UserName="AirtelUser" SubmitterRef="022-123456789" />
  </OrderForProduct>

2 comments:

Christoffer Pettersson said...
This comment has been removed by the author.
Christoffer Pettersson said...

Hi.

I am curious about the security concerning this. Do you know how it is possible to allow that a specific class can be used?

Because in theory, someone could add:

xmlns:java="java"

to the namespaces and then:

<xsl:value-of select="java:lang.System.exit(0)" />

Which basically quits your application. Meaning, that XSL can now contain malicious code.

I know "XMLConstants.FEATURE_SECURE_PROCESSING" denies all calls to Java method, but have you stumbled across a way to add rules?

Total Pageviews