4

I have an XSD file with content as:

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:simpleType name="phoneType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Voice"/>
      <xs:enumeration value="Fax"/>
      <xs:enumeration value="Pager"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="Contact">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Name">
          <xs:simpleType>
            <xs:restriction base="xs:string"></xs:restriction>
          </xs:simpleType>
        </xs:element>
        <xs:element name="Title"
                    type="xs:string" />
        <xs:element name="Phone"
                    minOccurs="1"
                    maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Number"
                          minOccurs="1">
                <xs:simpleType>
                  <xs:restriction base="xs:string"></xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="Type"
                          default="Voice"
                          minOccurs="1"
                          type="phoneType"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Using XSLT i want to generate XML like:

<Contact>
  <Name>name</Name>
  <Title>title</Title>
  <Phone>
    <Number>number</Number>
    <Type>Voice</Type>
  </Phone>
</Contact>

How to get above XML file as output of XSLT transformer?

4
  • How would the XSLT know that it's supposed to put name inside the Name element? Should it assume you want a lowercased copy of the element name if there's no default value? Commented Nov 23, 2015 at 4:02
  • @JLRishe yes i want to put element name itself. Commented Nov 23, 2015 at 6:57
  • This is.. ambitious. It's not an insignificant piece of work to craft an XSLT to do this, to be honest I think you're far better off attempting to do so yourself and asking questions about any problems you encounter that you're unable to solve on your own. It's also been attempted before, such as here: crimulus.com/2012/04/13/… Commented Nov 23, 2015 at 9:51
  • 1
    The link provided by @Flynn1179 no longer works. Here is an archived copy of that website. And here is an archived copy of the .xsl file discussed on that website. Commented Oct 22, 2020 at 20:10

1 Answer 1

2

This makes no attempt at generality but produces the requested output, and may give you a start

$ saxon9 x.xsd xsdgen.xsl 
<Contact>
   <Name>name</Name>
   <Title>title</Title>
   <Phone>
      <Number>number</Number>
      <Type>Voice</Type>
   </Phone>
</Contact>

using the xsl:

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        >
 <xsl:strip-space elements="*"/>
 <xsl:output indent="yes" omit-xml-declaration="yes"/>

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

 <xsl:template match="xsl:sequence">
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="xs:element/xs:simpleType">
  <xsl:value-of select="lower-case(../@name)"/>
 </xsl:template>

 <xsl:template match="@type[.='xs:string']">
  <xsl:value-of select="lower-case(../@name)"/>
 </xsl:template>

 <xsl:template match="@type[not(../*)][../@default]" priority="2">
  <xsl:value-of select="../@default"/>
 </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.