I need to create a XSD schema based on a XML file. Are there any Perl modules which can do this?
You can create the XSD by a XSL transformation using any XSLT processor. See XML::XSLT
An XSD file contains two element types: simple and complex. All leaf nodes have to be translated into simple type elements and the others have to be translated into complex types. Leaf nodes are nodes without any descendants. The corresponding XPath is //*[not(descendant::element())]
. The following XSLT implements this approch:
<?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">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsl:for-each select="//*[not(descendant::element())]">
<xsl:element name="xs:element">
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xsl:element>
</xsl:for-each>
<xsl:for-each select="//*[descendant::element()]">
<xsl:element name="xs:element">
<xsl:attribute name="name">
<xsl:value-of select="name()"/>
</xsl:attribute>
<xs:complexType>
<xs:sequence>
<xsl:for-each select="child::*">
<xsl:element name="xs:element">
<xsl:attribute name="ref">
<xsl:value-of select="name()"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xs:sequence>
</xs:complexType>
</xsl:element>
</xsl:for-each>
</xs:schema>
</xsl:template>
</xsl:stylesheet>
The following example:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<firstname>Peter</firstname>
<lastname>Pan</lastname>
<born>
<year>1904</year>
<month>12</month>
<day>27</day>
</born>
</person>
Will produce the following schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="firstname">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="lastname">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="year">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="month">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="day">
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstname"/>
<xs:element ref="lastname"/>
<xs:element ref="born"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="born">
<xs:complexType>
<xs:sequence>
<xs:element ref="year"/>
<xs:element ref="month"/>
<xs:element ref="day"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With