How to create wsproxy with xslt transformation in jboss-esb - web-services

JBoss ESB 4.11
Hello!
I work with the JBoss ESB 4.11, we are create webservice proxy and we need transform the payload message with xslt transformation. But I can find any functional example to use.
This is a example of the original message
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cim:ESRGERAL xmlns:cim="http://iec.ch/TC57/2007/profile#">
<cim:Terminal>
<cim:mRID>_012345_term</cim:mRID>
<cim:aliasName>term01</cim:aliasName>
<cim:name>term01</cim:name>
and this is the xslt file
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="*">
<ESRGERAL xmlns:cim="http://iec.ch/TC57/2007/profile#">
<xsl:for-each select="//cim:Terminal">
<Terminal>
<mRID>
<xsl:value-of select="cim:mRID"/>
</mRID>
<name>
<xsl:value-of select="cim:aliasName"/>
</name>
</Terminal>
</xsl:for-each>
</cim:ESRGERAL>
</xsl:template>
</xsl:stylesheet>
I need to help to create the correct configuration in jboss-esb.xml, this two files work fine when I use a java implementation, but I can make the same in jboss esb.

If you want to use XSLT for transforming XML-payloads then I believe the XsltAction is what you are looking for:
http://docs.jboss.org/jbossesb/docs/4.11/manuals/html/Programmers_Guide/index.html#OOB-transformers-xsltaction
Not sure that this fully answers your question but in any case, your use case seems very straight forward so I believe JBoss ESB will support it right out of the box without the need for custom code.
One caveat is if you really need to use XSLT 2.0 and not XSLT 1.0 (like in your example), then you will need to do something to make it load your 2.0 XSLT library instead of the standard.

Related

saxon transform vs saxon.jar document() behave differently

I have a stylesheet with a document() function. It finds the external document when i run it with saxon's transform on .Net, but not when i run it using java -jar saxon...
Please tell me that is well documented behavior and where it is documented!
Thank you guys!
EDIT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<root>
<xsl:variable name="dict" select="document('file:../data/mpxvoc.xml')"/>
<xsl:message>
<xsl:value-of select="doc-available('file:../data/mpxvoc.xml')"/>
<xsl:value-of select="$dict/*/*[1]"/>
</xsl:message>
</root>
</xsl:template>
</xsl:stylesheet>
EDIT2: Yes, same version!
EDIT3: Beginning of -t output on .NET/transform
C:\Users\mauri\OneDrive\smbdata\EM\SM-Plains\20200806>transform -t -s:2-MPX\vfix.mpx -xsl:C:\Users\mauri\eclipse-workspace\Pipeline\xsl\dtest.xsl -o:o.xml
Saxon-HE 9.9.1.6N from Saxonica
.NET 4.0.30319.42000 on Microsoft Windows NT 6.2.9200.0
URIResolver.resolve href="file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl" base="null"
Stylesheet compilation time: 1.25987s (1259.87ms)
Processing file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx
Using parser org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:///C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 222.8786ms
Tree size: 42580 nodes, 902487 characters, 26182 attributes
Building tree for file:///C:/Users/mauri/eclipse-workspace/Pipeline/data/mpxvoc.xml using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 59.3813ms
Tree size: 20788 nodes, 725994 characters, 10214 attributes
...
Java version:
C:\Users\mauri\OneDrive\smbdata\EM\SM-Plains\20200806>java -jar "C:\Program Files\Saxonica\SaxonHE10-2J\saxon-he-10.2.jar" -t -s:2-MPX\vfix.mpx -xsl:C:\Users\mauri\eclipse-workspace\Pipeline\xsl\dtest.xsl -o:o.xml
Saxon-HE 10.2J from Saxonica
Java version 1.8.0_261
Stylesheet compilation time: 635.9066ms
Processing file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:/C:/Users/mauri/OneDrive/smbdata/EM/SM-Plains/20200806/2-MPX/vfix.mpx using class net.sf.saxon.tree.tiny.TinyBuilder
Tree built in 348.0487ms
Tree size: 42580 nodes, 902487 characters, 26182 attributes
URIResolver.resolve href="file:../data/mpxvoc.xml" base="file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl"
falseError FODC0002 while evaluating xsl:message at line 12 of file:/C:/Users/mauri/eclipse-workspace/Pipeline/xsl/dtest.xsl: Document has been marked not available: file:../data/mpxvoc.xml
Execution time: 414.5074ms
Memory used: 62Mb
URIResolver shows different bases. Is that it and is there a quick fix to get the same result in java?
The URI file:../data/mpxvoc.xml is not a valid URI acccording to RFC 8089. Saxon however takes a liberal approach to URIs, in this context it passes the URI to the XML parser "as is", and if the parser is prepared to accept it then that's fine. At this point differences between platforms may well appear.
The solution is to avoid using URIs that don't conform to the standards. If you want a relative URI resolved against the base URI of the stylesheet, then drop the "file:" part.
RFC 8089 was only published in 2017, and until then the specs for the file URI scheme were hopelessly vague. The 2017 spec was far too late to make a real difference, since by then existing platforms like Java and .NET had to maintain compatibility with their respective past decisions. But if you stick to RFC 8089, you should be able to achieve reasonable portability.

wso2ei-6.4.0 and XSLT 3.0 support

I am planning to used XSL version 3.0 for my WSO2 EI application. Because, I need to map JSON to JSON and JSON to XML in my application. Currently I have try with version 2.0. Please refer following code for current implementation.
I need to know how change this version and which jar required in WSO2EI for xsl version 3.0.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="STATIC_BODY_PARAM"></xsl:param>
<xsl:template match="/availabilityRequest">
<availabilityRequest>
<control>
<userName>
<xsl:value-of select="control/userName" />
</userName>
<passWord>
<xsl:value-of select="control/passWord" />
</passWord>
</control>
....................
</availabilityRequest>
</xsl:template>
</xsl:stylesheet>
When I used version as 3.0, I got following error message. I have added your further reference.
ERROR - XSLTMediator Error creating XSLT transformer using : Value {name ='null', expression =fn:concat('gov:repository/transformation/',$ctx:uri.var.travel_type,'_',$ctx:uri.var.activity,'_',$ctx:uri.var.supplier_id,'_in.xslt')}
net.sf.saxon.trans.LicenseException: Requested feature (XSLT 3.0) requires Saxon-PE
at net.sf.saxon.Configuration.checkLicensedFeature(Configuration.java:584)
at net.sf.saxon.PreparedStylesheet.setStylesheetDocument(PreparedStylesheet.java:331)
at net.sf.saxon.PreparedStylesheet.prepare(PreparedStylesheet.java:207)
at net.sf.saxon.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:132)
at org.apache.synapse.mediators.transform.XSLTMediator.createTemplate(XSLTMediator.java:467)
I don't know anything specifically about WSO2EI, but it appears (from your link) that it is currently running with some older version of Saxon-HE.
Simply substituting the Saxon 9.9 JAR file for the one that is distributed with the product may work, or it may not. It's very likely to work, but it's possible that the stylesheets, or the calling application, depend on something in Saxon that has changed.
If you've tried something, there's no point telling us it doesn't work. You need to tell us exactly how it failed.
You should try running a stylesheet that outputs the value of system-property('xsl:product-version') so you have positive confirmation of which Saxon version is being picked up.
You don't need to make any changes to your stylesheets to use XSLT 3.0 features, but it's a good idea to change the version attribute to version="3.0" for documentation reasons.
I have fixed above problem using following information.
I got the 30 trail license key with registering http://www.saxonica.com/download/download.xml (saxon-license.lic) and it put into /wso2ei-6.4.0/ folder
Remove this jar (saxon.he_9.4.0.wso2v1.jar) on following location. (/wso2ei-6.4.0/wso2/components/plugins)
Also put this jar (saxon9ee.jar) http://www.saxonica.com/download/SaxonEE9-4-0-6J.zip into /wso2ei-6.4.0/lib location
Restart the wso2ei-6.4.0 server
Now xsl:stylesheet version="3.0" working without any issue.
I have got those details from following link. Many thanks for that.
http://nandikajayawardana.blogspot.com/2012/12/how-to-replace-saxonhe940wso2v1jar-in.html

XSLT Getting two different output for same input XML for same XSL

I have been trying my XSLT code in the online tool [XSLT 1.0 processor]:
http://www.freeformatter.com/xsl-transformer.html
Recently, I had to make use of xs:dateTime and hence started using the tool that uses XSLT 2.0 processor,
http://xsltransform.net/
Now, when i was trying to solve a problem, i see that i get different output for the same input XML in these two processors. The code posted here is not the real code i am working on; this is to simulate the weird output i faced.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<book>
<title></title>
</book>
<phone>apple</phone>
</items>
XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:template match="/">
<items><xsl:apply-templates select="items/*" /></items>
</xsl:template>
<!-- ignore empty elements -->
<xsl:template match="*[not(normalize-space())]" />
<xsl:template match="book">
<newbook><xsl:apply-templates /></newbook>
</xsl:template>
<xsl:template match="title">
<newtitle><xsl:apply-templates /></newtitle>
</xsl:template>
<xsl:template match="phone">
<newphone><xsl:apply-templates /></newphone>
</xsl:template>
</xsl:stylesheet>
Output from http://xsltransform.net/ : [output 1]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newbook>
<newtitle/>
</newbook>
<newphone>apple</newphone>
</items>
Output from http://www.freeformatter.com/xsl-transformer.html : [output 2]
<?xml version="1.0" encoding="UTF-8"?>
<items>
<newphone>apple</newphone>
</items>
Expected output XML is output 2 .
Any idea why this different output behavior?
note: I looked at another SO question: Generating two different outputs for the same XSL file?, but that is different.
Edit
To add more clarity on which tool produced which output:
http://xsltransform.net/ produced output 1
http://www.freeformatter.com/xsl-transformer.html produced output 2
Update[02/10/2014] - regarding solution
Since the correct answer was first provided by Jim Garrison, that's marked as answer. However, there are other important points as well, as pointed out by others, Hence I am wrapping up all here.
<xsl:template match="*[not(normalize-space())]" />
The above template eliminates the empty nodes in both XSLT1 and XSLT2. Hence output 2 is correct
*Reason for getting output 1 from the tool - http://xsltransform.net/ :*
As #michael.hor257k pointed out, there are two templates that matches the <book> element.
The tool was using Saxon-HE 9.5.1.3, and the output 1 behavior was probably a bug that was fixed in the latest maintenance release [#Michael Kay explained well in his answer]
As #Ian Roberts mentioned in his answer, there is a concept of default priorities that are assigned to different types of templates.
Changing the template syntax to:
<xsl:template match="*[not(normalize-space())]" priority="2"/>
yields the same output in both the tools regardless of Saxon version, because we are explicitly defining the priority to the template.
Output 2 is correct. I ran your example in Oxygen/XML, using both XSLT1 and XSLT2 and got the correct results for both. Your template
<xsl:template match="*[not(normalize-space())]" />
eliminates the empty nodes in both XSLT1 and XSLT2.
Therefore the only possible conclusion is that the online tool that produced your Output 1 has a bug.
I get the correct result running with Saxon-EE 9.5.1.4; the xsltransform site is running Saxon-HE 9.5.1.3. It's probably a bug that we fixed in the latest maintenance release; I'll do some chasing to see if I can finger it.
Note that an empty <book> element matches two of your templates:
<xsl:template match="*[not(normalize-space())]" />
and:
<xsl:template match="book">
<newbook><xsl:apply-templates /></newbook>
</xsl:template>
The same thing applies to an empty <title> element. Such conflicts must be resolved by the XSLT processor, using the priorities specified in the XSLT specification.
The result you report from http://xsltransform.net/ is generated by Saxon 9.5.1 - an XSLT 2.0 engine. You will get a different result (on the same site) if you switch to an XSLT 1.0 engine (Saxon 6.5 or Xalan 2.7.1).
I don't know if the conflict resolution rules have changed in XSLT 2.0 compared to XSLT 1.0; I am getting a different result myself when using Saxon 8.9 - also an XSLT 2.0 processor. Perhaps we will be fortunate enough to hear from Michael Kay regarding this difference (I have added a Saxon tag to your question to get his attention)..
Output 2 is definitely the correct one according to both the 1.0 and 2.0 XSLT specs for the stylesheet you give in the question. However you say this is simplified when compared to your real stylesheet.
The thing that makes it work is the default priorities that are assigned to different types of templates. These are the same in both XSLT versions, and a match pattern that involves a predicate will overrule one that is just a single element name test.
However a match that involves hierarchy (e.g. match="items/book") or anything more complex than just a single element name will get the same priority as the *[....] rule by default - 0.5. If you've got any of these kinds of patterns in your real XSLT then you need to add an explicit priority higher than 0.5 to the "blank-suppressor" template.
<xsl:template match="*[not(normalize-space())]" priority="2"/>

Copy elements with Namespaces using XSLT

I want to copy the namespaces in the elements. The namespace attribute and its value may vary and can occur in any element. But I want to copy the namespace as it is. Also I should not include any attribute as additional to copy the namespace. I am using Saxon 9(he) XSLT processor for transformations
In the below XML file, I am getting the element <ct-ext:case> with the "xmlns:ct-ext" attribute missing. I tried copy-namespaces="yes", yet I am not getting the correct output. I am writing a common XSLT for various DTDs.
Sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<ct:doc identifier="GPPCIA702661235" xsi:schemaLocation="http://test.com/test test.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ct="http://test.com/test" xmlns="http://www.w3.org/1998/Math/MathML" xmlns:ct-ext="http://test.com/test-ext">
<ct:doc-meta identifier="EHIXRW383636159">
<ct:para><ct:inline-math identifier="RCSNDD453018159"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mi>$</mi><mn>1.65</mn></mrow></math></ct:inline-math></ct:para>
<ct-ext:case identifier="CDVOXU875594216" xmlns:ct-ext="http://test.com/test-ext">
<ct:simple-meta identifier="HNKRFT326435269">
<ct:title identifier="CGSVLX990515344">This is title</ct:title>
</ct:simple-meta>
</ct-ext:case>
</ct:doc-meta>
</ct:doc>
Output Required:
<?xml version="1.0" encoding="UTF-8"?>
<ct:doc identifier="GPPCIA702661235" xsi:schemaLocation="http://test.com/test test.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ct="http://test.com/test" xmlns="http://www.w3.org/1998/Math/MathML" xmlns:ct-ext="http://test.com/test-ext">
<ct:doc-meta identifier="EHIXRW383636159">
<ct:para><ct:inline-math identifier="RCSNDD453018159"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mi>$</mi><mn>1.65</mn></mrow></math></ct:inline-math></ct:para>
<ct-ext:case identifier="CDVOXU875594216" xmlns:ct-ext="http://test.com/test-ext">
<ct:simple-meta identifier="HNKRFT326435269">
<ct:title identifier="CGSVLX990515344">This is title</ct:title>
</ct:simple-meta>
</ct-ext:case>
</ct:doc-meta>
</ct:doc>
XSLT tried:
<?xml version='1.0'?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ct="http://test.com/test" xmlns="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:ct-ext="http://test.com/test-ext">
<xsl:output method="xml" encoding="UTF-8" indent="no"/>
<xsl:template match="#*|node()">
<xsl:copy copy-namespaces="yes">
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Whether you use copy-namespaces or not does not matter (yes is the default anyway), if the input XML has a duplicated namespace declaration on an inner element node then the data model the XSLT processor operates on is not different from the one produced if the inner namespace declaration were not present.
So
<root xmlns:ct-ext="http://test.com/test-ext">
<ct-ext:case xmlns:ct-ext="http://test.com/test-ext">...</ct-ext:case>
</root>
does not differ from
<root xmlns:ct-ext="http://test.com/test-ext">
<ct-ext:case>...</ct-ext:case>
</root>
Consequently when serializing the copied result tree the originally duplicated namespace declaration is lost. I don't think there is a way with XSLT to prevent that.
To elaborate on what Martin said: you are putting requirements on XML tools (like XSLT) that they're not designed to fulfill.
It will help if we use more precise terminology. What you're asking to copy are not namespaces, but rather namespace declarations.
XML tools are designed to be able to produce specified XML elements (and other nodes) in the namespaces that you specify them to be in. This is part of the XML information model.
XML tools are not required to let you specify what namespace prefixes to use, or where to put namespace declarations, so long as the output XML has the right elements and attributes in the right namespaces.
So the requirements you're specifying should not be necessary for any downstream XML consumer. Maybe if you explain why you want namespace declarations to come out in a certain way, we can help you find ways to achieve those purposes, ways that are compatible with how XML namespaces are designed to work.

How do I get the current folder path within an XSLT file?

Is there a way to get the current folder path from within a XSLT file?
I need it to locate other XML and XSLT files. We have different customer folders and will need to successfully find the correct files.
You can send it into the style-sheet from outside using xsl:param. Then you need to determine what the current path is when invoking the from the outside ;)
In MSXSL on Windows, you can use a script extension like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://tempuri.org/msxsl"
>
<msxsl:script language="JScript" implements-prefix="user">
<![CDATA[
var fso = new ActiveXObject("Scripting.FileSystemObject");
function getCurrentPath(){
return fso.GetFolder(".").Path
}
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:getCurrentPath()"/>
</xsl:template>
</xsl:stylesheet>
Other XSL processors support similar methods to use external resources (scripting languages, function libraries etc.), so this is just an example.
Is there a way to get the current
folder path from within a xslt file?
Need it to locate other xml and xslt
files
No need for any extension functions or even parameters to do that!
Any relative URLs used in the href attribute of an <xsl:import> or <xsl:include>
instruction are resolved based on the URL of the current XSLT stylesheet -- it only needs to have an URL, which is vlearly stated as true in the question above. This is very convenient in importing/including XSLT stylesheets.
The document() function also will resolve a relative URL in a similar way, thus making any additional XML document accessible using anrelative URL.
Lastly, here is an example how this facilities are massively used in a big library of XSLT functions and templates (FXSL 2.x):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://fxsl.sf.net/"
exclude-result-prefixes="xs xdt f"
>
<!--
This module contains the FXSL versions of the "standard" XPath functions
These are intended as convenience functions, so that they can be passed
as parameters to other functions (e.g. to f:zipWith())
or curried and passed as parameters (e.g. to f:map())
-->
<xsl:import href="func-curry.xsl"/>
<xsl:import href="func-compose-flist.xsl"/>
<xsl:import href="func-standardArithmeticXpathFunctions.xsl"/>
<xsl:import href="func-standardBooleanXpathFunctions.xsl"/>
<xsl:import href="func-standardStringXpathFunctions.xsl"/>
<xsl:import href="func-standardNodesXpathFunctions.xsl"/>
<xsl:import href="func-standardSequencesXpathFunctions.xsl"/>
<xsl:import href="func-standardAggregateXpathFunctions.xsl"/>
<xsl:import href="func-standardDateTimeXpathFunctions.xsl"/>
<xsl:import href="func-standardXSLTXpathFunctions.xsl"/>
<xsl:import href="func-standardAxisXpathFunctions.xsl"/>
</xsl:stylesheet>
This may work for your setup:
<xsl:value-of select="system-property('user.dir')"/>
For example,
<xsl:value-of select="document(concat(system-property('user.dir'),'/',filename,'.xml'))//title[1]"/>
no...
but you could maybe workaround the problem by using relative URLs and/or passing parameters into the stylesheet.
In most XSLT processor, you can add custom functions as extensions. For example here is Saxon's documentation how to do that.
Not AFAIK (though you could always pass it as a param to the transform), but I'm not clear why relative paths won't work for you here.