8 Replies Latest reply on Jul 23, 2007 11:24 AM by tfennelly

    full XSL Transformation

      Hello,

      I am trying to deploy a .esb archive with a simple xsl transformation. I cannot get it to work...

      Idealy I would like to have a self-contained archive without using the web console. I am using the 4.2MR3 release with the smooks.esb deployed?

      Could you help me to get the configuratio right?

      Thanks!
      Mathieu

      The file I would like to transform is:

      <?xml version="1.0" encoding="UTF-8"?>
      <addresses
       xmlns="http://xmlns.babelgom.com/2007/smf/addresses"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.babelgom.com/2007/smf/addresses addresses.xsd">
       <address fname="AAAAA" lname="-AAA-" mobile="+32478595433">11111</address>
       <address fname="BBBBB" lname="-BBB-" workphone="+3223548874">22222</address>
       <address fname="CCCCC" lname="-CCC-" workphone="+3223333333">33333</address>
       <address fname="DDDDD" lname="-DDD-" mobile="+37837837833">44444</address>
      </addresses>




      the xslt is:
      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:addresses="http://xmlns.babelgom.com/2007/smf/addresses" xmlns="http://xmlns.babelgom.com/2007/smf/csv" version="2.0" exclude-result-prefixes="addresses">
       <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
       <xsl:template match="/">
       <!--/csv-->
       <xsl:element name="csv">
       <!--/csv/headers-->
       <xsl:element name="headers">
       <!--/csv/headers/header[1]-->
       <xsl:element name="header">
       <xsl:value-of select="'Firstname'"/>
       </xsl:element>
       <!--/csv/headers/header[2]-->
       <xsl:element name="header">
       <xsl:value-of select="'Lastname'"/>
       </xsl:element>
       <!--/csv/headers/header[3]-->
       <xsl:element name="header">
       <xsl:value-of select="'Address'"/>
       </xsl:element>
       </xsl:element>
       <!--/csv/line-->
       <xsl:for-each select="/addresses:addresses/addresses:address">
       <xsl:element name="line">
       <!--/csv/line/field[1]-->
       <xsl:element name="field">
       <xsl:value-of select="@fname"/>
       </xsl:element>
       <!--/csv/line/field[2]-->
       <xsl:element name="field">
       <xsl:value-of select="@lname"/>
       </xsl:element>
       <!--/csv/line/field[3]-->
       <xsl:element name="field">
       <xsl:value-of select="concat(/addresses:addresses/addresses:address[1],'-',/addresses:addresses/addresses:address[2])"/>
       </xsl:element>
       </xsl:element>
       </xsl:for-each>
       </xsl:element>
       </xsl:template>
      </xsl:stylesheet>




      My smooks-res.xml file looks like this:

      <?xml version='1.0' encoding='UTF-8'?>
      <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.0.xsd">
       <resource-config selector="addresses" >
       <resource>/addresses-csv.xsl</resource>
       <param name="is-xslt-templatelet">false</param>
       </resource-config>
      </smooks-resource-list>



      My jboss-esb.xml lokks like this:
      <?xml version="1.0" encoding="utf-8"?>
      <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" parameterReloadSecs="5">
       <providers>
       <jms-provider name="internalbus" connection-factory="ConnectionFactory" jndi-context-factory="org.jnp.interfaces.NamingContextFactory" jndi-URL="localhost" jndi-pkg-prefix="">
       <jms-bus busid="account-1_hub-1_default_internalbus">
       <jms-message-filter dest-type="QUEUE" dest-name="queue/internalbus" />
       </jms-bus>
       </jms-provider>
       <ftp-provider name="FTPIn" hostname="localhost">
       <ftp-bus busid="FTPIn">
       <ftp-message-filter username="user1" password="password" passive="true" directory="/a" input-suffix=".dat" work-suffix=".esbWorking" post-delete="true" post-suffix=".COMPLETE" post-directory="/a/processed" error-delete="false" error-suffix=".HAS_ERROR" error-directory="/a/error" />
       </ftp-bus>
       </ftp-provider>
       </providers>
      
       <services>
       <service category="category" name="service" description="description">
       <listeners>
       <jms-listener name="internalbus" busidref="internalbus" maxThreads="1" />
       <ftp-listener name="FTPIn" busidref="FTPIn" maxThreads="1" is-gateway="true" poll-frequency-seconds="10" ></ftp-listener>
       </listeners>
      
       <actions>
       <action name="print-before" class="org.jboss.soa.esb.actions.SystemPrintln">
       <property name="message" value="Message before transformation" />
       </action>
      
       <action name="transform" class="org.jboss.soa.esb.actions.converters.SmooksTransformer">
       <property name="resource-config" value="/smooks-res.xml" />
       </action>
       <action name="print-after" class="org.jboss.soa.esb.actions.SystemPrintln">
       <property name="message" value="Message after transformation" />
       </action>
       </actions>
       </service>
       </services>
      </jbossesb>


        • 1. Re: full XSL Transformation
          tfennelly

          And what exactly is happening?

          Can you make your XSLT even more basic (really simple - eliminate possible namespace issues etc). Hopefully this will validate that Smooks is in fact applying the XSLT. If that's successful, then your down to issues within the XSLT.

          I notice also that you haven't set the type on the xslt resource i.e. it should be as follows:

          <resource-config selector="addresses" >
           <resource type="xsl">/addresses-csv.xsl</resource>
           <param name="is-xslt-templatelet">false</param>
          </resource-config>
          


          If this is not set, Smooks has no idea how to apply the XSL resource - it doesn't know what "type" of resource it is.

          Have you run any of the transformation quickstarts supplied within the MR3 distro? If not, give them a try too. The transform_xmltoxml_simple quickstart demos a really simple (silly) XSLT based transform.

          • 2. Re: full XSL Transformation
            tfennelly

            Actually, the type not being set should be OK. Smooks would infer the type from the resource file extension, which is "xsl". So that's probably not your problem at all. Sorry :-)

            Try the other things however + the distro quickstarts etc.

            • 3. Re: full XSL Transformation

              Thanks for your answer. It was indeed a problem with my xsl transformation. It was not easy to find due to unfortunate log4j configuration...

              At debug level, the original javax.xml.transform.TransformerException stack trace is swallowed in org.milyn.delivery.dom.ContentDeliveryConfigImpl:

              if(logger.isDebugEnabled()) {
               logger.warn("ContentDeliveryUnitCreator [" + creator.getClass().getName() + "] unable to create resource processing instance for resource [" + resourceConfig + "]. " + thrown.getMessage());
              


              Thanks again

              • 4. Re: full XSL Transformation
                tfennelly

                So you can only see the exception when you turn on debug logging?

                If so, I'll add an info log at the relevant code (XslContentDeliveryUnitCreator). It's probably just passing the exception up assuming it will get info logged.

                • 5. Re: full XSL Transformation

                  So I went back to my original problem. Indeed the problem is namespaces.

                  Everything is fine when the xsl transformation start with:


                  <?xml version="1.0" encoding="UTF-8"?>
                  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:addresses="http://xmlns.babelgom.com/2007/smf/addresses" xmlns="http://xmlns.babelgom.com/2007/smf/csv" version="2.0" exclude-result-prefixes="addresses">
                  <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
                  <xsl:template match="addresses:addresses">


                  but if I change the match pattern to "/" or "addresses" nothing is selected:


                  <?xml version="1.0" encoding="UTF-8"?>
                  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:addresses="http://xmlns.babelgom.com/2007/smf/addresses" xmlns="http://xmlns.babelgom.com/2007/smf/csv" version="2.0" exclude-result-prefixes="addresses">
                  <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
                  <xsl:template match="/">


                  this transformation works outside of Smooks... anyway I found a workaround :-) Thanks.

                  • 6. Re: full XSL Transformation
                    tfennelly

                     

                    "mathieu" wrote:
                    this transformation works outside of Smooks... anyway I found a workaround :-) Thanks.


                    I'm not surprised that matching against "/" breaks the XSLT under Smooks because Smooks is fragment based i.e. transforms are not targeted at the *whole document*. You can target XSL transforms at fragments of your message e.g. you could target an XSL transform at just the "address" elements. Even if you're targeting at "$document", this is really just the root element (root fragment) of the document i.e. not the Document node. If you're interested, I posted a flash demo of the Smooks DOM Processing Model.

                    Not sure why "addresses:addresses" Vs just "addresses" is not consistent with how you're performing this transform outside Smooks. Can you post the code here? Are you using DOMSource, SAXSource or StreamSource? Are you using the same XSL Processor in both cases?

                    Interesting observations though... thanks :-)

                    • 7. Re: full XSL Transformation

                      The code is exactly the one posted earlier. I tested the transformation using Xalan and saxon 8.9 (my target) with the same results. Here is the code I used outside Smooks:

                      public String applyXsl(Reader xml, Reader xsl) {
                       try {
                       Writer writer = new StringWriter();
                       applyXsl(new StreamSource(xml), new StreamSource(xsl), new StreamResult(writer));
                       writer.flush();
                       String retVal = writer.toString();
                       writer.close();
                       return retVal;
                       } catch (Exception e) {
                       throw ...
                       }
                       }
                      
                       public void applyXsl(Source xml, Source xsl, Result result) throws TransformerException {
                       System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
                      
                       TransformerFactory factory = TransformerFactory.newInstance();
                       factory.setURIResolver(new LocalUriResolver());
                       Templates tpl = factory.newTemplates(xsl);
                       Transformer transformer = tpl.newTransformer();
                      
                       transformer.transform(xml, result);
                      
                       }





                      BTW: I based my code on the following example that makes use of the "/" : http://svn.codehaus.org/milyn/trunk/smooks-examples/xslt-namespaces/smooks-config.xml

                      • 8. Re: full XSL Transformation
                        tfennelly

                         

                        "mathieu" wrote:
                        BTW: I based my code on the following example that makes use of the "/" : http://svn.codehaus.org/milyn/trunk/smooks-examples/xslt-namespaces/smooks-config.xml


                        OK, well so much for that theory then :-) In reality though (from a Smooks perspective), I don't think the sample shouldn't really me matching on the root of the document (should just match against the current context node i.e. ".") so I'll check into that example.

                        I'll use what you've supplied here to look into this in a bit more detail - thanks :-)

                        So you OK now? Do you have any feedback on anything else?