Search code examples
xsltxsdwsdljax-wsflatten

XSL to Flatten JAX-WS WSDL


I have several JAX-WS generated WSDLs which include an xsd:import, one of the clients isn't capable of stitching the two together, so I'm looking to flatten the WSDL into a single file.

I have this WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mypackage.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://mypackage.com/" name="ws">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://mypackage.com/" schemaLocation="the.xsd"/>
        </xsd:schema>
    </types>
    <!-- ... -->
</definitions>

and the referenced XSD:

<?xml version='1.0' encoding='UTF-8'?>

<xs:schema xmlns:tns="http://mypackage.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://mypackage.com/">

    <xs:element name="getSomething" type="tns:getSomething"/>

    <xs:element name="getSomethingResponse" type="tns:getSomethingResponse"/>

    <xs:complexType name="getSomething">
        <xs:sequence>
            <xs:element name="blahOne" type="xs:string" minOccurs="0"/>
            <xs:element name="blahTwo" type="xs:int"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="getSomethingResponse">
        <xs:sequence>
            <xs:element name="return" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

</xs:schema>

and the XSL I'm using to transform:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
    <xsl:output method="xml" indent="no"/>
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>    
    <xsl:template match="xs:import">
        <xsl:variable name="schema" select="@schemaLocation"/>
        <xsl:apply-templates select="document($schema)"/>
    </xsl:template>
</xsl:stylesheet>

Gives the result:

<?xml version="1.0"?>
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mypackage.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://mypackage.com/" name="ws">
    <types>
        <xsd:schema>
            <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://mypackage.com/">

                <xs:element name="getSomething" type="tns:getSomething"/>

                <xs:element name="getSomethingResponse" type="tns:getSomethingResponse"/>


                <xs:complexType name="getSomething">
                    <xs:sequence>
                        <xs:element name="blahOne" type="xs:string" minOccurs="0"/>
                        <xs:element name="blahTwo" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>

                <xs:complexType name="getSomethingResponse">
                    <xs:sequence>
                        <xs:element name="return" type="xs:string" minOccurs="0"/>
                    </xs:sequence>
                </xs:complexType>


            </xs:schema>
        </xsd:schema>
    </types>
    <!-- ... -->
</definitions>

... and the problem is that I need to have the targetNamespace="http://mypackage.com/" defined on the outer: xsd:schema, or alternatively if I could drop the tags and somehow convert the xsd namespace prefix from "xs" to "xsd", what am I doing wrong?


Solution

  • A colleague pointed me in the right direction. I simply needed to remove the outer xsd:schema element, so I modified the xsl to this:

    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        version="1.0">
        <xsl:output method="xml" indent="no"/>
    
        <xsl:template match="node() | @*">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
        </xsl:template>  
    
        <xsl:template match="xs:import">
            <xsl:variable name="schema" select="@schemaLocation"/>
            <xsl:apply-templates select="document($schema)"/>
        </xsl:template>
    
        <xsl:template match="xsd:schema[not(@targetNamespace)]">
            <xsl:apply-templates/>
        </xsl:template>     
    
    </xsl:stylesheet>