I want to extract inline schema from a WSDL file. But, I don't know how to perform XSL transformation for that. Any help on creating such a stylesheet would be great.
thanks a lot,
This one is working for me:
<?xml-stylesheet type="text/xsl"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" />
<xsl:template match='text()' />
<xsl:template match="//s:schema">
<xsl:copy-of select='.'/>
</xsl:template>
</xsl:stylesheet>
It assumes your inline schema uses the http://www.w3.org/2001/XMLSchema namespace.
This is what you can do when the wsdl contains more than one schema-elements:
Use xsd-split.xslt from
https://gist.github.com/ebratb/3819949
to to split the *.wsdl file into several *.xsd files.
You can use the maven plugin to run the 2.0 xslt with Saxon ( see http://www.mojohaus.org/xml-maven-plugin/examples/transform-saxon.html )
Then write a small schema file that just imports those generated *.xsd files plus the official definition of the soap envelope.
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://your.company.com/dummy" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://<target namespace of the first xsd file>" schemaLocation="file:///path/to/first.xsd" />
<xsd:import namespace="http://<target namespace of the second xsd file>" schemaLocation="file:///path/to/second.xsd" />
...
<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/" />
</xsd:schema>
When using a custom Resource Resolver, the schemaLocation attributes are not needed.
Related
I use xslt-saxon to transform xml file. XML parser works complitly fine on Saxon 10.6 but after upgrade to Saxon-HE 11.4 it skips closing tags and read another tags as input. It only occurs if there are only spaces in between tag. If there is any letters or nothing it works fine.
<Tag0>
<Tag1>sample1</Tag1>
<Tag2> </Tag2>
<Tag3>sample2</Tag3>
</Tag0>
ends as
<Tag0 Tag1="sample1"
Tag2=" <Tag2>
<Tag3>sample2</Tag2>
"/>
xslt file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:element name="{MsgStr}message" namespace="{$msgNamespace}">
<xsl:element name="Tag1" namespace="{$Namespace}">
<xsl:attribute name="Tag2"><xsl:value-of select="*:Tag2"/></xsl:attribute>
<xsl:attribute name="Tag3"><xsl:value-of select="*:Tag3"/></xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I tried put *:Tag2/text() but without any results.
This is very strange behaviour, and it's not really possible to investigate it without a complete repro. Your example is clearly incomplete: the stylesheet contains undeclared variables, etc. I suspect a Saxon bug, if only a failure to detect and report something you are doing wrong. Please try to put together a repro (that is, everything needed for someone else to reproduce the effect) and post it at saxonica.plan.io.
I have a huge xml schema which contains lots of unused xsd with their schema locations. These are not reffered any where in the whole file. Is there a way to remove these unused imported xsds and do the cleanup using xslt.
Run them through an identity transform with specialized empty templates matching the xs:import elements that you want to remove. The exact criteria depends on how you can identify the unused (filename, within a directory, etc).
Here is an example of how to exclude a particular schema import, identifying it by the filename in the #schemaLocation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!--example of how to remove an import like:
<xs:import schemaLocation="some/path/to/unwanted-schema.xsd"/>
-->
<xsl:template match="xs:import[ends-with(#schemaLocation, 'unwanted-schema.xsd')]"/>
</xsl:stylesheet>
You could expand the match criteria, or create several empty templates matching the unwanted xs:import elements. All other content will be copied forward and preserved.
I am using Apache Camel file component and xslt component. I have a route where i pickup a xml message, transform using xslt and drop to a different folder.
Apache camel DSL route:
<route id="normal-route">
<from uri="file:{{inputfilefolder}}?consumer.delay=5000" />
<to uri="xslt:stylesheets/simpletransform.xsl transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl" />
<to uri="file:{{outputfilefolder}}" />
</route>
I am mentioning Apache camel also here , to check if there is a way to set the output file name using Camel. I think, even without Camel, there would be a mechanism with pure XSLT.
I need to rename the transformed output file. But always i am getting the same input filename with the transformed content, in the output folder.
eg: input file: books.xml
output file: books.xml [with the transformation applied]
What i am looking for is someotherfilename.xml as the output filename. The output data is correct.
I tried <xsl:result-document href="{title}.xml"> , but then the output xml is blank. Please help.
Input XML file:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book.child.1>
<title>Charithram</title>
<author>P Sudarsanan</author>
</book.child.1>
<book.child.2>
<title>Java Concurrency</title>
<author>Joshua Bloch</author>
</book.child.2>
</books>
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:variable name="filename" select="'newfilename'" />
<xsl:template match="/">
<xsl:result-document href="{$filename}.xml">
<traders>
<xsl:for-each select="books/*">
<trade>
<title>
<xsl:value-of select="title" />
</title>
</trade>
</xsl:for-each>
</traders>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
Output XML when using <xsl:result-document href="" in XSLT
it is blank..
Output XML when not using <xsl:result-document href="" in XSLT
<?xml version="1.0" encoding="UTF-8"?>
<traders xmlns:xs="http://www.w3.org/2001/XMLSchema">
<trade>
<title>Charithram</title>
</trade>
<trade>
<title>Java Concurrency</title>
</trade>
</traders>
Edit: edited the XSLT as per MartinHonnen's comment
Looks like Camel's default is to use the same file name, but you can override it. As the docs mention you can specify the options of interest as follows:
file:directoryName[?options]
One such option is fileName:
Use Expression such as File Language to dynamically set the filename.
For consumers, it's used as a filename filter. For producers, it's
used to evaluate the filename to write.
In short, modify your route as follows:
<route id="normal-route">
<from uri="file:{{inputfilefolder}}?consumer.delay=5000" />
<to uri="xslt:stylesheets/simpletransform.xsl transformerFactoryClass=net.sf.saxon.TransformerFactoryImpl" />
<to uri="file:{{outputfilefolder}}?fileName=foo.xml" />
</route>
Where foo.xml will be the output file.
Update
You can use Simple or File language to set file names dynamically. There are a few examples in the links.
I'm generating Java from WSDL using wsimport (JAX-WS 2.1.3) and need to make it generate a #HandlerChain annotation. So I create a JAX-WS binding file:
<jaxws:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
wsdlLocation="../etc/MessageStudio.wsdl">
<jaxws:bindings node="wsdl:definitions">
<javaee:handler-chain>
<javaee:handler-chain-name>StrongmailHandlers</javaee:handler-chain-name>
<javaee:handler>
<javaee:handler-name>OrganizationTokenHandler</javaee:handler-name>
<javaee:handler-class>com.bossmedia.strongmailadapter.deliveryadapter.OrganizationTokenHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</jaxws:bindings>
and run the wsimport Ant task:
<wsimport
wsdl="../etc/MessageStudio.wsdl"
sourcedestdir="../src/gen"
destdir="../classes"
verbose="false"
binding="../etc/jaxws.bindings.xml">
</wsimport>
but I get no annotation and no handler chain XML file. Googling only finds me solutions for changing packages, methods and arguments and the JAX-WS RI page from where I copied the XML.
Could you help me find the flaw in my configuration or another way, short of modifying the generated code, to get my handler into the chain?
The answer is that the RI example is incorrect. There needs to be a handler-chains wrapper tag:
<jaxws:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
wsdlLocation="../etc/MessageStudio.wsdl">
<jaxws:bindings node="wsdl:definitions">
<javaee:handler-chains>
<javaee:handler-chain>
<javaee:handler-chain-name>StrongmailHandlers</javaee:handler-chain-name>
<javaee:handler>
<javaee:handler-name>OrganizationTokenHandler</javaee:handler-name>
<javaee:handler-class>com.bossmedia.strongmailadapter.deliveryadapter.OrganizationTokenHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
</jaxws:bindings>
It turns out that the generated handler chain file is put in the output directory (target/package) where the compiled class files are. If you want to change that, you can use the "destDir" option to do that. Also, set "xnocompile" to false else the generated class files will end up in the same directory as the handler file. Wish they didn't do such a half a**ed job at documentation.
There is still an error in the example. The tag <javaee:handler-chain-name> does not exist according to the XML scheme (http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/javaee_web_services_metadata_handler_2_0.xsd).
The correction is:
<jaxws:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
wsdlLocation="../etc/MessageStudio.wsdl">
<jaxws:bindings node="wsdl:definitions">
<javaee:handler-chains>
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-name>OrganizationTokenHandler</javaee:handler-name>
<javaee:handler-class>com.bossmedia.strongmailadapter.deliveryadapter.OrganizationTokenHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
I have an XML file that looks like
<?xml version='1.0' encoding='UTF-8'?>
<root>
<node name="foo1" value="bar1" />
<node name="foo2" value="bar2" />
</root>
I have a method
String processBar(String bar)
and I want to end up with
<?xml version='1.0' encoding='UTF-8'?>
<root>
<node name="foo1" value="processBar("bar1")" />
<node name="foo2" value="processBar("bar2")" />
</root>
Is there an easy way to do this? Preferably in Java. Note that the file is too large to safely load completely into memory. The data in the XML roughly arbitrary and processBar may be complex, so I don't want to use regular expressions.
Assuming you mean replacing the attribute values with the result of calling processBar on said attribute values...
Use the JDK's XSLT API to run the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:java="http://xml.apache.org/xalan/java"
extension-element-prefixes="java">
<xsl:template match="/root/node/#value">
<xsl:attribute name="value">
<xsl:value-of select="java:com.example.yourclass.processBar(string(.))"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
This uses the Xalan-Java extensions and assumes a static method. You can get an instance of an object and store it in an xsl:variable, like this:
<xsl:variable name="frobber" select="java:com.example.Frobber.new()"/>
<xsl:value-of select="java:processBar($frobber, string(.))"/>
Or somesuch.
This only works with Xalan, but since that's the XSLT processor distributed with the JDK, I doubt it will be onerous to use Xalan.
you can either parse the whole thing in a java xml parser OR just get the file content into a string and then do a regexp replace on it (using i.e. http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29)