RE: [xsl] Calling java from xsl - with xml as parameter

Subject: RE: [xsl] Calling java from xsl - with xml as parameter
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 6 Dec 2007 17:51:18 -0000
My feeling is that you need to write a processing pipeline above the XSLT
level: you should use a technology such as XProc (or Orbeon, or Ant, etc) to
invoke a sequence of processing steps each of which can be implemented
either in Java or XSLT (or anything else).

That's not to say that you can't use XSLT as the control layer, but I don't
think it's necessarily the best approach.

I think that the basic problem you've got (at the coding level) is that you
have a tree representation of the document at the XSLT level, and you are
calling a Java method that expects a serialized representation. Either the
caller or the callee needs to change. Passing a tree, of course, is more
efficient than passing serialized XML and reparsing it.

Michael Kay
http://www.saxonica.com/



> -----Original Message-----
> From: richardtrans@xxxxxx [mailto:richardtrans@xxxxxx] 
> Sent: 06 December 2007 17:30
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: [xsl] Calling java from xsl - with xml as parameter
> 
> Hi thank you for your response. I have read a lot of your xsl stuff.
> 
> We use xsl version 1.0 and xerces / xalan.
> I will try have a look at saxon:serialize()
> 
> My real problem is probably, that we have a design problem, 
> but nothing i can do about that. Unfortunately. I cant change it.
> 
> We hava an xml (xml1 - Invoice.xml), which actually is an invoice. 
> Content of xml1 changes all the time.
> The xml1 is transformed with an xsl (xsl1).
> And the result is another xml, lets name it xml2.
> All normal procedure. No problem so far.
> But from the xsl1 i need (given the design) to call a java method
> (rtrtransform(...)) with xml1 as parameter 
> "object2Transform". The method uses Apache fop to generate a 
> pdf document (a byte array) from the "object2Transform" and 
> another xsl (xsl2).
> The pdf bytes will be changed to string and returned from the 
> java method. The pdf must be put into xml2 in the tags 
> /Envelope/Attachment/EmbeddedDocumentBinaryObject
> 
> Generating the pdf is normally not a problem, but having to 
> pass the xml as a parameter from the xsl is the problem.
> 
> Is it possible?
> 
> **********************************************************
> 
> The xsl:
> 
> <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet 
> version="1.0" xmlns:xsl="http://www.w3.
> org/1999/XSL/Transform" 
> 	xmlns:main="http://rep.oio.dk/ubl/xml/schemas/0p71/maindoc/";
> 	xmlns:com="http://rep.oio.dk/ubl/xml/schemas/0p71/common/"; 
> 	xmlns:pie="http://rep.oio.dk/ubl/xml/schemas/0p71/pie/"; 
> 	xmlns:tpcm="http://rep.oio.dk/ubl/xml/schemas/0p71/testpcm/"; 
> 	xmlns:tpcp="http://rep.oio.dk/ubl/xml/schemas/0p71/testpcp/"; 
> 	xmlns:tpie="http://rep.oio.dk/ubl/xml/schemas/0p71/testpie/"; 
> 	xmlns:tpip="http://rep.oio.dk/ubl/xml/schemas/0p71/testpip/"; 
> 	xmlns:pip="http://rep.oio.dk/ubl/xml/schemas/0p71/pip/"; 
> 	xmlns:pcm="http://rep.oio.dk/ubl/xml/schemas/0p71/pcm/"; 
> 	xmlns:pcp="http://rep.oio.dk/ubl/xml/schemas/0p71/pcp/"; 
> 	
> xmlns:transf="dk.edbgruppen.genericdocumentprocess.transformation.
> TransformManagerImpl" 
> 	exclude-result-prefixes="main com pie tpcm tpcp tpie 
> tpip pip pcm pcp transf"
> 	>
> 	<xsl:output method="xml" version="1.0" encoding="UTF-8" 
> indent="yes" 
> />
> 	<xsl:strip-space elements="*" />
> 
> <xsl:variable name="xmlString">
> 	<xsl:copy-of select="/*[local-name()='Invoice']" /> 
> </xsl:variable>
> 
> 
> <xsl:template match="/">
> 	<xsl:apply-templates 
> select="/*[local-name()='Invoice']" /> </xsl:template>
> 
> 
> <xsl:template match="main:Invoice | pip:Invoice | pie:Invoice | pcm:
> Invoice | tpcm:Invoice | tpcp:Invoice | tpie:Invoice | 
> tpip:Invoice | pcp:Invoice">
>  	<xsl:variable name="pdfBytes">
> 		<xsl:value-of 
> select="transf:rtrtransform(string($xmlString))"/>
> 	</xsl:variable>
> 
>  	<Envelope>
> 		<DocumentType>Invoice</DocumentType>
> 		<MailingDate>2007-11-20</MailingDate>
> 		<EnvelopeType>C5</EnvelopeType>
> 		<EnvelopeLayout>NoName</EnvelopeLayout>
> 		<PaperType>A4</PaperType>
> 		<PaperLayout>Sender</PaperLayout>
> 		<PrintColorType>Color</PrintColorType>
> 		<NumberOfCopies>1</NumberOfCopies>
> 		<NumberOfPages>xxx</NumberOfPages>
> 		<xsl:for-each select="com:SellerParty">
> 			<SenderInfo>
> 				<EndpointID>
> 					<xsl:attribute name="schemeID">
> 						<xsl:value-of 
> select="com:ID/@schemeID" />
> 					</xsl:attribute>
> 					<xsl:value-of select="com:ID" />
> 				</EndpointID>
> 				<Name><xsl:value-of 
> select="com:PartyName/com:Name" /></Name>
> 				<xsl:choose>
> 					<xsl:when 
> test="com:Address/com:ID='Betaling'">
> 						
> <PostalZone><xsl:value-of select="com:Address[com:ID='Betaling']
> /com:PostalZone" /></PostalZone>
> 						
> <CountryCode><xsl:value-of select="com:Address[com:ID='Betaling']
> /com:Country/com:Code" /></CountryCode>
> 					</xsl:when>
> 					<xsl:otherwise>
> 						
> <PostalZone><xsl:value-of select="com:Address[position()=1]/com:
> PostalZone" /></PostalZone>
> 						
> <CountryCode><xsl:value-of select="com:Address[position()=1]/com:
> Country/com:Code" /></CountryCode>
> 					</xsl:otherwise>
> 				</xsl:choose>
> 			</SenderInfo>
> 		</xsl:for-each>
> 		<xsl:choose>
> 			<xsl:when 
> test="count(com:BuyerParty[com:Address/com:
> ID='Fakturering'])=1">
> 				<xsl:apply-templates 
> select="com:BuyerParty[com:Address/com:
> ID='Fakturering']" />
> 			</xsl:when>
> 			<xsl:when 
> test="count(com:BuyerParty[com:Address/com:ID='Juridisk'])
> =1">
> 				<xsl:apply-templates 
> select="com:BuyerParty[com:Address/com:
> ID='Juridisk']" />
> 			</xsl:when>
> 			<xsl:otherwise>
> 				<xsl:apply-templates 
> select="com:BuyerParty[position()=1]" />
> 			</xsl:otherwise>
> 		</xsl:choose>
> 		<Attachment>
> 			<EmbeddedDocumentBinaryObject>
> 				<!-- Here i want to put the 
> generatet pdf document -->
> 				<xsl:value-of select="$pdfBytes" />
> 			</EmbeddedDocumentBinaryObject>
> 		</Attachment>
> 	</Envelope>
> </xsl:template>
> 
> <xsl:template match="com:BuyerParty">
> 	<ReceiverInfo>
> 		<EndpointID>
> 			<xsl:attribute name="schemeID">
> 				<xsl:value-of 
> select="../com:BuyersReferenceID/@schemeID" />
> 			</xsl:attribute>
> 			<xsl:value-of 
> select="../com:BuyersReferenceID" />
> 		</EndpointID>
> 		<Name><xsl:value-of 
> select="com:PartyName/com:Name" /></Name>
> 		<PostalZone><xsl:value-of 
> select="com:Address/com:PostalZone" 
> /></PostalZone>
> 		<CountryCode><xsl:value-of 
> select="com:Address/com:Country/com:Code" 
> /></CountryCode>
> 	</ReceiverInfo>
> </xsl:template>
> </xsl:stylesheet>
> 
> **********************************************************
> 
> Example of the xml:
> <?xml version="1.0" encoding="UTF-8"?>
> <Invoice xmlns="http://rep.oio.dk/ubl/xml/schemas/0p71/pie/"; xmlns:
> egx="http://tastselv.truelink.dk/xsd/egx/"; xmlns:xsi="http://www.w3.
> org/2001/XMLSchema-instance" xmlns:main="http://rep.oio.
> dk/ubl/xml/schemas/0p71/maindoc/" xmlns:com="http://rep.oio.
> dk/ubl/xml/schemas/0p71/common/" xsi:schemaLocation="http://rep.oio.
> dk/ubl/xml/schemas/0p71/pie/ http://rep.oio.
> dk/ubl/xml/schemas/0p71/pie/pielax.xsd">
> 	<com:ID>1</com:ID>
> 	<com:IssueDate>2007-09-20</com:IssueDate>
> 	<com:TypeCode>PIE</com:TypeCode>
> 	<main:InvoiceCurrencyCode>DKK</main:InvoiceCurrencyCode>
> 	<com:BuyersReferenceID schemeID="EAN">9999999999987</com:
> BuyersReferenceID>
> 	<com:ReferencedOrder>
> 		<com:BuyersOrderID>VAGN</com:BuyersOrderID>
> 		<com:SellersOrderID>1484500</com:SellersOrderID>
> 		<com:IssueDate>0001-01-01</com:IssueDate>
> 	</com:ReferencedOrder>
> 	<com:BuyerParty>
> 		<com:ID schemeID="CVR">48470610</com:ID>
> 		<com:PartyName>
> 			<com:Name>HR. PrintService 
> repraesentant, Richard Trans</com:Name>
> 		</com:PartyName>
> 		<com:Address>
> 			<com:ID>Fakturering</com:ID>
> 			<com:Street>HOVEDGADEN 50 1.</com:Street>
> 			<com:AdditionalStreet/>
> 			<com:HouseNumber/>
> 			<com:CityName>Kolding</com:CityName>
> 			<com:PostalZone>6000</com:PostalZone>
> 			<com:Country>
> 				<com:Code listID="ISO 
> 3166-1">DK</com:Code>
> 			</com:Country>
> 		</com:Address>
> 		<com:BuyerContact>
> 			<com:ID>n/a</com:ID>
> 		</com:BuyerContact>
> 	</com:BuyerParty>
> 	<com:SellerParty>
> 		<com:ID schemeID="CVR">57765313</com:ID>
> 		<com:PartyName>
> 			<com:Name>Fridolf EG TEST</com:Name>
> 		</com:PartyName>
> 		<com:Address>
> 			<com:ID>Betaling</com:ID>
> 			<com:Street>Vejen 5</com:Street>
> 			<com:AdditionalStreet/>
> 			<com:HouseNumber/>
> 			<com:InhouseMail>300</com:InhouseMail>
> 			<com:CityName>Kolding</com:CityName>
> 			<com:PostalZone>6000</com:PostalZone>
> 			<com:Country>
> 				<com:Code listID="ISO 
> 3166-2">DK</com:Code>
> 			</com:Country>
> 		</com:Address>
> 		<com:PartyTaxScheme>
> 			<com:CompanyTaxID 
> schemeID="CVR">57765313</com:CompanyTaxID>
> 		</com:PartyTaxScheme>
> 		<com:OrderContact>
> 			<com:ID>21</com:ID>
> 			<com:Name>21</com:Name>
> 		</com:OrderContact>
> 	</com:SellerParty>
> 	<com:PaymentMeans>
> 		<com:TypeCodeID>71</com:TypeCodeID>
> 		<com:PaymentDueDate>2007-10-15</com:PaymentDueDate>
> 		
> <com:PaymentChannelCode>INDBETALINGSKORT</com:PaymentChannelCode>
> 		<com:PaymentID>010010003000000</com:PaymentID>
> 		<com:JointPaymentID>81500000</com:JointPaymentID>
> 	</com:PaymentMeans>
> 	<com:PaymentTerms>
> 		<com:ID>SPECIFIC</com:ID>
> 		<com:RateAmount currencyID="DKK">100.00</com:RateAmount>
> 	</com:PaymentTerms>
> 	<com:TaxTotal>
> 		<com:TaxTypeCode>VAT</com:TaxTypeCode>
> 		<com:TaxAmounts>
> 			<com:TaxableAmount 
> currencyID="DKK">3630.52</com:TaxableAmount>
> 			<com:TaxAmount 
> currencyID="DKK">907.63</com:TaxAmount>
> 		</com:TaxAmounts>
> 		<com:CategoryTotal>
> 			
> <com:RateCategoryCodeID>VAT</com:RateCategoryCodeID>
> 			
> <com:RatePercentNumeric>25</com:RatePercentNumeric>
> 			<com:TaxAmounts>
> 				<com:TaxableAmount 
> currencyID="DKK">3630.52</com:TaxableAmount>
> 				<com:TaxAmount 
> currencyID="DKK">907.63</com:TaxAmount>
> 			</com:TaxAmounts>
> 		</com:CategoryTotal>
> 	</com:TaxTotal>
> 	<com:LegalTotals>
> 		<com:LineExtensionTotalAmount 
> currencyID="DKK">3630.52</com:
> LineExtensionTotalAmount>
> 		<com:ToBePaidTotalAmount currencyID="DKK">4538.15</com:
> ToBePaidTotalAmount>
> 	</com:LegalTotals>
> 	<com:ExtensibleContent>
> 		<egx:ExtInfo>
> 			<egx:SenderSystem>EG409</egx:SenderSystem>
> 			<egx:TermsOfDeliveryText>Afhentet 
> lager</egx:TermsOfDeliveryText>
> 		</egx:ExtInfo>
> 	</com:ExtensibleContent>
> </Invoice>
> 
> 
> 
> **********************************************************
> The java class and method (very simplified):
> 
> package dk.edbgruppen.genericdocumentprocess.transformation;
> 
> import java.sql.Timestamp;
> import java.util.Date;
> import java.util.HashMap;
> import java.util.Map;
> import java.util.StringTokenizer;
> 
> import org.w3c.dom.Document;
> 
> import dk.edbgruppen.core.xml.XMLHelper; import 
> dk.edbgruppen.framework.domain.gdoctype.GDatatype;
> import dk.edbgruppen.framework.domain.gdoctype.Inbox;
> import dk.edbgruppen.framework.domain.gdoctype.LayoutXslSender;
> import dk.edbgruppen.framework.domain.gdoctype.Subtype;
> import dk.edbgruppen.framework.domain.gdoctype.Transformer;
> import dk.edbgruppen.framework.domain.singletons.SSubtypes;
> import dk.edbgruppen.framework.service.IStorefrontService;
> import dk.edbgruppen.framework.service.IStorefrontServiceFactory;
> import dk.edbgruppen.framework.service.StorefrontServiceFactory;
> import dk.edbgruppen.genericdocumentprocess.documentdata.
> DocumentDataImpl;
> import dk.edbgruppen.genericdocumentprocess.documentdata.
> IDocumentData;
> import dk.edbgruppen.genericdocumentprocess.exceptionhandling.
> GenericDocumentException;
> import dk.edbgruppen.genericdocumentprocess.memberIdToresolver.
> MemberResolverManagerImpl;
> import dk.edbgruppen.genericdocumentprocess.transaction.
> DocumentProcessThread;
> import dk.edbgruppen.genericdocumentprocess.transaction.GenericThread;
> import dk.edbgruppen.xml.XPathGetter;
> 
> public class TransformManagerImpl implements ITransformManager {
>   public static String rtrtransform(String object2Transform) 
> { //This is just a test method.
> //The real method will call another program (apache fop) and 
> generate pdf bytes.
> //Bytes will be changed to String before return.
> 	try {
> 		System.out.println("OK " + object2Transform);
> 		return object2Transform;
> 	} catch (Exception ex) {
> 		//ex.printStackTrace();
> 		System.out.println("Error " + object2Transform);
> 		return "Error";
> 	}
>   }
> }
> 
> **********************************************************
> 
> 
> ----Oprindelig meddelelse----
> Fra: mike@xxxxxxxxxxxx
> Dato: 06/12/2007 17:37
> Til: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> Emne: RE: [xsl] Calling java from xsl - with xml as parameter
> 
> 
> Calling extension functions from XSLT depends on the XSLT 
> processor you are using, so we can't answer without that information.
> 
> You haven't said what the Java method signature is. It sounds 
> to me as if the Java method is expecting a string, and so the 
> call is taking the string value of the supplied node, just as 
> it would when you call an XPath function that expects a 
> string. But you actually seem to want the Java method to get 
> the XML serialization of the node - you won't get that 
> automatically, you will have to call a function such as 
> saxon:serialize() to get it.
> 
> What is your Java method actually doing?
> 
> > I thought i could solve the problem by using xsl:copy-of 
> select... , 
> > but that seems to be illegal:
> > 	<xsl:value-of
> > select="transf:rtrtransform(string(<xsl:copy-of select="
> 
> Well, yes, you can't have XSLT instructions in the middle of 
> an XPath expression (or XML elements in the middle of an XML 
> attribute). The fact that you're making this mistake suggests 
> we ought to start from first principles and look at the 
> problem you are trying to solve and whether your whole 
> approach makes sense.
> 
> Michael Kay
> http://www.saxonica.com/ 
> 
> > -----Original Message-----
> > From: richardtrans@xxxxxx [mailto:richardtrans@xxxxxx]
> > Sent: 06 December 2007 16:20
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: [xsl] Calling java from xsl - with xml as parameter
> > 
> > Hi.
> > 
> > I hava a xml and a xsl which are being parsed.
> > 
> > In the xsl i want to call a java method with a parameter, which 
> > contains the source xml. The parameter can be of any type.
> > The java program returns a String.
> > 
> > The problem is to send the xml as parameter to the java method.
> > 
> > I have tried following:
> > Copy / Store the xml document in the variable xmlString.
> > <xsl:variable name="xmlString">
> > 	<xsl:copy-of select="/*[local-name()='Invoice']" /> 
> </xsl:variable>
> > 
> > Send the xmlString to the java method rtrtransform, but the problem 
> > is, that it only sends the values to the java method.
> > When i want to send "<abc><d>hi</d><e>there<e></abd>", i only get 
> > "hithere". Tags are not send.
> > <xsl:variable name="myresult">
> > 	<xsl:value-of select="transf:rtrtransform(string($xmlString))"/>
> > </xsl:variable>
> > 
> > 
> > I thought i could solve the problem by using xsl:copy-of 
> select... , 
> > but that seems to be illegal:
> > 	<xsl:value-of
> > select="transf:rtrtransform(string(<xsl:copy-of select="
> > abc" />"/>
> > or
> > 	<xsl:value-of select="transf:rtrtransform(string(<xsl:copy-of
> > select=&#034;abc&#034; />"/>
> > 
> > 
> > Any solutions to this?
> > 
> > Best regards
> > Richard Trans
> > 
> > --
> ~------------------------------------------------------------------
> > XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> > To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
> > or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
> > --~--

Current Thread