Russian doll to Venetian blind xsl transformation

xsd, xslt

Solution

You could start off, in your root template, by simply selecting all of you complex types in the xsd

<xsl:apply-templates select="//xs:complexType" />

You would then have a template to match complex types, which don't have a name, so you can simply output them with a name based on their parent element.

<xsl:template match="xs:complexType[not(@name)]">
    <xs:complexType name="{../@name}Type">
        <xsl:apply-templates/>
    </xs:complexType>
</xsl:template>

Finally, you would have a template to match the elements with a complex type, and add a type attribute

<xsl:template match="xs:element[xs:complexType]">
    <xs:element type="{@name}Type">
        <xsl:apply-templates select="@*" />
    </xs:element>
</xsl:template>

Here is the full XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes='exsl'>
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="GX" targetNamespace="GX" elementFormDefault="qualified" attributeFormDefault="unqualified">
      <!-- processing starts here from the root element -->
      <xsl:apply-templates select="//xs:complexType" />
    </xs:schema>
  </xsl:template>

  <xsl:template match="xs:complexType[not(@name)]">
    <xs:complexType name="{../@name}Type">
      <xsl:apply-templates/>
    </xs:complexType>
  </xsl:template>

  <xsl:template match="xs:element[xs:complexType]">
    <xs:element type="{@name}Type">
      <xsl:apply-templates select="@*" />
    </xs:element>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

When applied to you XSD XML the following is output

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tns="GX"
           targetNamespace="GX"
           elementFormDefault="qualified"
           attributeFormDefault="unqualified">
  <xs:complexType name="topType">
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="REQUESTOR" nillable="false" type="xs:string"/>
      <xs:element type="RETURN_CANCELLED_CUSTOMERSType" maxOccurs="1" minOccurs="0" name="RETURN_CANCELLED_CUSTOMERS" nillable="false"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="RETURN_CANCELLED_CUSTOMERSType">
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="EXTERNAL_CUSTOMER_ID" nillable="false" type="xs:string"/>
      <xs:element maxOccurs="1" minOccurs="1" name="ON_BEHALF_OF" nillable="false" type="xs:string"/>
      <xs:element type="MSISDN_aaaType" maxOccurs="1" minOccurs="0" name="MSISDN_aaa" nillable="false"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MSISDN_aaaType">
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="GSP_ID" nillable="false" type="xs:string"/>
      <xs:element type="MSISDN_bbbType" maxOccurs="1" minOccurs="0" name="MSISDN_bbb" nillable="false"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MSISDN_bbbType">
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="SSPP_ID" nillable="false" type="xs:string"/>
      <xs:element type="MSISDN_cccType" maxOccurs="1" minOccurs="0" name="MSISDN_ccc" nillable="false"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MSISDN_cccType">
    <xs:sequence>
      <xs:element maxOccurs="1" minOccurs="0" name="SSPC_ID" nillable="false" type="xs:string"/>
      <xs:element maxOccurs="1" minOccurs="0" name="MSISDN_ddd" nillable="false" type="xs:string"/>
      <xs:element maxOccurs="1" minOccurs="0" name="IMSI" nillable="false" type="xs:string"/>
      <xs:element maxOccurs="1" minOccurs="0" name="MSISDN" nillable="false" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Problem

I have been trying to write an xslt transformation to convert 'Russian doll' style xsd into 'Venetian blind' one. I have written something but that does not work exactly as I intended. so I have the following xsd document: ``` <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="GX" targetNamespace="GX" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:complexType name="topType"> <xs:sequence> <xs:element name="REQUESTOR" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="RETURN_CANCELLED_CUSTOMERS" nillable="false" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="EXTERNAL_CUSTOMER_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="ON_BEHALF_OF" type="xs:string" nillable="false" minOccurs="1" maxOccurs="1"/> <xs:element name="MSISDN_aaa" nillable="false" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="GSP_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_bbb" nillable="false" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="SSPP_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_ccc" nillable="false" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element name="SSPC_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_ddd" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="IMSI" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:schema> ``` which I try to transform in to: ``` <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="GX" targetNamespace="GX" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:complexType name="topType"> <xs:sequence> <xs:element name="REQUESTOR" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="RETURN_CANCELLED_CUSTOMERS" type="tns:RETURN_CANCELLED_CUSTOMERSType" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> <xs:complexType name="RETURN_CANCELLED_CUSTOMERSType"> <xs:sequence> <xs:element name="EXTERNAL_CUSTOMER_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="ON_BEHALF_OF" type="xs:string" nillable="false" minOccurs="1" maxOccurs="1"/> <xs:element name="MSISDN_aaa" type="tns:MSISDN_aaaType" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> <xs:complexType name="MSISDN_aaaType"> <xs:sequence> <xs:element name="GSP_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_bbb" type="tns:MSISDN_bbbType" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> <xs:complexType name="MSISDN_bbbType"> <xs:sequence> <xs:element name="SSPP_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_ccc" type="tns:MSISDN_cccType" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> <xs:complexType name="MSISDN_cccType"> <xs:sequence> <xs:element name="SSPC_ID" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN_ddd" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="IMSI" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> <xs:element name="MSISDN" type="xs:string" nillable="false" minOccurs="0" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:schema> ``` the XSLT I am writing is very much work in progress and I am struggling ... did anyone did a similar thing and could offer a piece of advice? basically I am stuck. ``` <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes='exsl'> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="GX" targetNamespace="GX" elementFormDefault="qualified" attributeFormDefault="unqualified"> <!-- processing starts here from the root element --> <xsl:apply-templates/> </xs:schema> </xsl:template> <xsl:template match="xs:complexType[not(@name)]"> <xs:complexType name="{../@name}Type"> <xs:sequence> <xsl:apply-templates/> <xs:element>current:<xsl:value-of select="./@name"/> parent: <xsl:value-of select="../@name"/> </xs:element> </xs:sequence> </xs:complexType> <xs:element>no name = parent: <xsl:value-of select="../@name"/> </xs:element> </xsl:template> <!--find the most nested complex type i.e. there are no more child complext types--> <xsl:template match="xs:complexType[not(xs:sequence/xs:element/xs:complexType)]"> <xs:complexType name="{../@name}Type"> <xsl:copy-of select="child::node()"/> <xs:element>current:<xsl:value-of select="./@name"/> parent: <xsl:value-of select="../@name"/>NO MORE NESTING!!!!!!!!!!!!!</xs:element> </xs:complexType> </xsl:template> <xsl:template match="xs:element"> <xsl:copy> <xsl:apply-templates select="attribute()"/> </xsl:copy> </xsl:template> <xsl:template match="attribute()"> <xsl:copy/> </xsl:template> <xsl:template match="xs:element[xs:complexType]"> <xs:element name="{@name}" type="{@name}Type" nillable="{@nillable}" minOccurs="{@minOccurs}" maxOccurs="{@maxOccurs}"/> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet> ```

Original source