Posts Tagged ‘XSLT’
Custom SOAP Faults in Apache ServiceMix 4
It can’t be realized without custom processors because although several expression languages can retrieve the exception message, neither the XQuery or XSLT components work with fault messages.
WSDL
<wsdl:definitions targetNamespace="http://www.fernandoribeiro.eti.br/ws/sample" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.fernandoribeiro.eti.br/ws/sample" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="http://www.fernandoribeiro.eti.br/ws/sample" xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
<xs:element name="SampleFault"> <!-- great opportunity for a common type -->
<xs:complexType>
<xs:sequence>
<xs:element name="Message" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
...
<wsdl:message name="SampleFault">
<wsdl:part name="SampleFault" element="tns:SampleFault" />
</wsdl:message>
<wsdl:portType name="SamplePortType">
<wsdl:operation name="SampleOperation">
...
<wsdl:fault name="SampleFault" message="tns:SampleFault" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SampleSoapBinding" type="tns:SamplePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
...
<wsdl:operation name="SampleOperation">
<soap:operation ... />
...
<wsdl:fault name="SampleFault">
<soap:fault name="SampleFault" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SampleService">
<wsdl:port name="SamplePort" binding="tns:SampleSoapBinding">
<soap:address location="http://ws.fernandoribeiro.eti.br/SampleService/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
RouteBuilder
package br.eti.fernandoribeiro.ws.sample;
import org.apache.camel.builder.RouteBuilder;
public final class SampleRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
onException(Exception.class).process(new SampleFaultProcessor());
...
}
}
Processor
package br.eti.fernandoribeiro.ws.sample;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public final class SampleFaultProcessor implements Processor {
private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance();
private DocumentBuilder builder;
public SampleFaultProcessor() throws ParserConfigurationException {
builder = FACTORY.newDocumentBuilder();
}
public void process(final Exchange exch) throws ParserConfigurationException {
final Document doc = builder.newDocument();
final Element root = doc.createElementNS("http://www.fernandoribeiro.eti.br/ws/sample", "SampleFault");
final Element msg = doc.createElementNS("http://www.fernandoribeiro.eti.br/ws/sample", "Message");
msg.setTextContent(exch.getException().getMessage());
root.appendChild(msg);
doc.appendChild(root);
exch.getFault().setBody(doc);
}
}
SOAP Response
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring/>
<detail>
<SampleFault xmlns="http://www.fernandoribeiro.eti.br/ws/sample">
<Message>Sample Message</Message>
</SampleFault>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Custom Actions for JBossESB
- DB Action
- File Reader Action
- HTTP Action
- Remove Message Property Action
- Set Message Property Action
- Splitter Action
- XSLT Action
https://jira.jboss.org/jira/browse/JBESB-3118 (vote for it!)
https://jira.jboss.org/jira/browse/JBESB-3125 (vote for it!)
https://jira.jboss.org/jira/browse/JBESB-3086 (vote for it!)
https://jira.jboss.org/jira/browse/JBESB-3087 (vote for it!)
https://jira.jboss.org/jira/browse/JBESB-3146 (vote for it!)
https://jira.jboss.org/jira/browse/JBESB-3089 (vote for it!)
Default Parameter Values in XSLT
<xsl:param name="Param">Value</xsl:param> <!-- you can use select instead -->
How to Parse XML in CDATA Sections with Saxon
Use the parse extension described here.
XML
<?xml version="1.0" encoding="UTF-8"?> <Root> <Element>Text</Element> </Root>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" exclude-result-prefixes="saxon" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/">
<xsl:template match="/">
<Root>
<Element><xsl:value-of select="saxon:parse(/Root/Element)"/></Element> <!-- no need to use text() -->
</Root>
</xsl:template>
</xsl:stylesheet>
How to Check for Omitted Attributes and Elements in XSLT
Attributes
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Root">
<Root>
<Element><xsl:choose><xsl:when test="not(@attribute)">Omitted</xsl:when><xsl:otherwise>Present</xsl:otherwise></xsl:choose></Element>
</Root>
</xsl:template>
</xsl:stylesheet>
Elements
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Root">
<Root>
<Element><xsl:choose><xsl:when test="not(Element)">Omitted</xsl:when><xsl:otherwise>Present</xsl:otherwise></xsl:choose></Element>
</Root>
</xsl:template>
</xsl:stylesheet>
How to Create Null Elements in XSLT and XQuery
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:template match="/Root">
<Root>
<Element>
<xsl:attribute name="xsi:nil">true</xsl:attribute>
</Element>
</Root>
</xsl:template>
</xsl:stylesheet>
XQuery
declare namespace xsi= "http://www.w3.org/2001/XMLSchema-instance";
<Root>
<Element>
{
attribute xsi:nil {true()}
}
</Element>
</Root>
Using nilled in XPath
Even though it was introduced in 2007, it ain’t supported by Apache Xalan (and therefore the JRE) yet. The only alternative seems to be Saxon-SA.
Document.xml (not pointing to the schema)
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element xsi:nil="true"/>
</Root>
Document.xml (pointing to the schema)
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Schema.xsd">
<Element xsi:nil="true"/>
</Root>
Schema.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Element" nillable="true">
<xs:complexType/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Stylesheet.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Root">
<Root>
<Element>
<xsl:choose>
<xsl:when test="nilled(Element)">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</Element>
</Root>
</xsl:template>
</xsl:stylesheet>
SaxonSASample1.java
- Doesn’t require the document to point to the location of the schema.
- Uses a transformer.
import java.io.FileReader;
import net.sf.saxon.FeatureKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
import static java.lang.System.out;
import com.saxonica.SchemaAwareTransformerFactory;
public final class SaxonSample {
public static void main(final String[] args) throws Exception {
final SchemaAwareTransformerFactory factory = (SchemaAwareTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory system property is set to com.saxonica.SchemaAwareTransformerFactory
factory.addSchema(new StreamSource("Schema.xsd"));
factory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final Transformer transformer = factory.newTransformer(new StreamSource(new FileReader("Stylesheet.xsl")));
transformer.transform(new SAXSource(new InputSource(new FileReader("Document.xml"))), new StreamResult(out));
}
}
SaxonSASample2.java
- Requires the document to point to the location of the schema.
- Uses a transformer.
import java.io.FileReader;
import net.sf.saxon.FeatureKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
import static java.lang.System.out;
public final class SaxonSASample2 {
public static void main(final String[] args) throws Exception {
final TransformerFactory factory = TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory system property is set to com.saxonica.SchemaAwareTransformerFactory
factory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final Transformer transformer = factory.newTransformer(new StreamSource(new FileReader("Stylesheet.xsl")));
transformer.transform(new SAXSource(new InputSource(new FileReader("Document.xml"))), new StreamResult(out));
}
}
It doesn’t work with a DOM source because the type annotations of all elements is stripped to xs:untyped by Saxon-SA, whether they have been validated or not.
SaxonSASample3.java
- Doesn’t require the document to point to the location of the schema.
- Uses a transformer handler.
import static java.lang.System.out;
import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.ValidatorHandler;
import net.sf.saxon.FeatureKeys;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public final class SaxonSASample3 {
public static void main(final String[] args) throws Exception {
final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
final SAXParser parser = parserFactory.newSAXParser();
final XMLReader reader = parser.getXMLReader();
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // ensure saxon9sa-jaxp.jar is in the classpath
final Schema schema = schemaFactory.newSchema();
final ValidatorHandler validatorHandler = schema.newValidatorHandler();
final SAXTransformerFactory transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory is set to com.saxonica.SchewaAwareTransformerFactory
transformerFactory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(new StreamSource(new FileReader("Stylesheet.xsl")));
transformerHandler.setResult(new StreamResult(out));
validatorHandler.setContentHandler(transformerHandler);
reader.setContentHandler(validatorHandler);
reader.parse(new InputSource(new FileReader("Document.xml")));
}
}
SaxonSASample4.java
- Requires the document to point to the location of the schema.
- Uses a transformer handler.
import static java.lang.System.out;
import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.ValidatorHandler;
import net.sf.saxon.FeatureKeys;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public final class SaxonSASample4 {
public static void main(final String[] args) throws Exception {
final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
final SAXParser parser = parserFactory.newSAXParser();
final XMLReader reader = parser.getXMLReader();
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // ensure saxon9sa-jaxp.jar is in the classpath
final Schema schema = schemaFactory.newSchema(new StreamSource(new FileReader("Schema.xsd")));
final ValidatorHandler validatorHandler = schema.newValidatorHandler();
final SAXTransformerFactory transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory is set to com.saxonica.SchemaAwareTransformerFactory
transformerFactory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(new StreamSource(new FileReader("Stylesheet.xsl")));
transformerHandler.setResult(new StreamResult(out));
validatorHandler.setContentHandler(transformerHandler);
reader.setContentHandler(validatorHandler);
reader.parse(new InputSource(new FileReader("Document.xml")));
}
}
You can work around in both Saxon-SA and Saxon-B by using:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/Root">
<Root>
<Element>
<xsl:choose>
<xsl:when test="Element/@xsi:nil = xs:boolean('true')">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</Element>
</Root>
</xsl:template>
</xsl:stylesheet>
http://saxon.markmail.org/message/a6wbxegxr4wlfkb5?q=fn:nilled
http://www.w3.org/TR/xmlschema-2/#boolean
Thanks to Michael for the support.
How to Use choose in XSLT
The following code checks for a null element to output 0 instead of its text value.
<xsl:choose>
<xsl:when test="not(nilled(Element))">
<xsl:value-of select="Element"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:choose