I am fairly new with XSLT and wondering how to change the XML SOAP message to add more tags in between
Source XML:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<DataValidationFailureFault xmlns="http://sample.com">
<ValidationErrorList>
<ValidationError>
<ErrorCode>1234</ErrorCode>
<ErrorString>Test Error</ErrorString>
</ValidationError>
</ValidationErrorList>
</DataValidationFailureFault>
</soapenv:Body>
</soapenv:Envelope>
After XSLT, I want the XML SOAP to look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>HardCoded Value</faultcode>
<faultstring>HardCoded Value</faultstring>
<detail>
<DataValidationFailureFault xmlns="http://sample.com">
<ValidationErrorList>
<ValidationError>
<ErrorCode>1234</ErrorCode>
<ErrorString>Test Error</ErrorString>
</ValidationError>
</ValidationErrorList>
</DataValidationFailureFault>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
Start with an identity tranform. Then, write another template to intervene in the identity copying process in the right place, namely when the soapenv:Body
element is processed.
XSLT Stylesheet
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="soapenv:Body">
<xsl:copy>
<soapenv:Fault>
<faultcode>HardCoded Value</faultcode>
<faultstring>HardCoded Value</faultstring>
<detail>
<xsl:apply-templates select="@*|node()"/>
</detail>
</soapenv:Fault>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML Output
By the way, sure you need all those unused namespace declarations?
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>HardCoded Value</faultcode>
<faultstring>HardCoded Value</faultstring>
<detail>
<DataValidationFailureFault xmlns="http://sample.com">
<ValidationErrorList>
<ValidationError>
<ErrorCode>1234</ErrorCode>
<ErrorString>Test Error</ErrorString>
</ValidationError>
</ValidationErrorList>
</DataValidationFailureFault>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
EDIT
just curious how do I remove the namespace in DataValidationFailureFault tag?
In this case, add another template to the stylesheet that matches the elements in that namespace (DataValidationFailureFault
and its descendants, too - it's a default namespace). Then, construct a new element without a namespace for each of them:
<xsl:template match="sample:DataValidationFailureFault|sample:DataValidationFailureFault//*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
and modify the stylesheet
element of the XSLT code to include a namespace declaration for the sample:
prefix and also exclude this prefix, since it becomes unused in the output.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sample="http://sample.com"
exclude-result-prefixes="sample">