Trang
Intro
Trang is a java based program used for inferring XML Schema (XSD) from a source XML document. It attempts to guess what kind of data-types should be used for the various elements in the XML file.
Get Trang
Download Trang from the following location:
» Trang download...
Use Trang
To infer a schema for an XML document, do the following:
- Download Trang (see above)
- Make sure the filename is trang.jar, and do not uncompress it
- Put Trang and the XML file you want to infer from into the same folder (if they are not already)
- Use this command to generate an XSD schema:
java -jar trang.jar xmlfile.xml schema.xsd (where 'xmlfile.xml' is your xml file's filename, and 'schema.xsd' is the filename for the new schema)
XML Schema
This example will be referred to in the following two sections on types.
Example: XML
<?xml version="1.0" encoding="utf-8"?>
<root>
<id>45</id>
<details>
<firstname>John</firstname>
<surname>Doe</surname>
<address>
<housenumber>76</housenumber>
<roadname>Pine Road</roadname>
<area>Winton</area>
<city>Bournemouth</city>
<county>Dorset</county>
<postcode>BH9 1AB</postcode>
</address>
</details>
<medical>
<allergies>
<allergy>Cat hair</allergy>
<allergy>Pollen</allergy>
</allergies>
<notes>Occasionally suffers from bouts of acute death.</notes>
</medical>
<salary>22000</salary>
</root>
Example: Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="id"/>
<xs:element ref="details"/>
<xs:element ref="medical"/>
<xs:element ref="salary"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="id" type="xs:integer"/>
<xs:element name="details">
<xs:complexType>
<xs:sequence>
<xs:element ref="firstname"/>
<xs:element ref="surname"/>
<xs:element ref="address"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="firstname" type="xs:NCName"/>
<xs:element name="surname" type="xs:NCName"/>
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element ref="housenumber"/>
<xs:element ref="roadname"/>
<xs:element ref="area"/>
<xs:element ref="city"/>
<xs:element ref="county"/>
<xs:element ref="postcode"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="housenumber" type="xs:integer"/>
<xs:element name="roadname" type="xs:string"/>
<xs:element name="area" type="xs:NCName"/>
<xs:element name="city" type="xs:NCName"/>
<xs:element name="county" type="xs:NCName"/>
<xs:element name="postcode" type="xs:string"/>
<xs:element name="medical">
<xs:complexType>
<xs:sequence>
<xs:element ref="allergies"/>
<xs:element ref="notes"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="allergies">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="allergy"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="allergy" type="xs:string"/>
<xs:element name="notes" type="xs:string"/>
<xs:element name="salary" type="xs:integer"/>
</xs:schema>
Explanation
The schema example above was inferred from the example xml file, using Trang.
Before moving on, it is important to note that since Trang is not a human, it does not act the same way a human would, when hand-writing a schema. A human would most likely define an XML schema in one of two ways:
- Define all elements in the same order they come in the document:
This can be the easiest and most logical approach, especially for some people, but can be difficult to manage on more complex examples, or in places where the same element is used in different places. - Define the elements, and then define their usage:
This method is probably the best, and most logical for larger and more complex documents. It allows you to define a type and reuse it in different areas of the document if necessary.
Trang uses a method a bit like the latter, but instead of starting with all the simple types and attributes (more on this later), and then moving to the complex types, and then finally defining the outer (root) element, Trang sort of does it backwards, starting at the outside top, and following the document down into the 'branches' and defining their types. This can sometimes make the inferred schema a bit hard to follow, but once you see what's going on, its not too difficult.
Detail
The first section inside the schema's root element decribes the outer element.
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="id"/>
<xs:element ref="details"/>
<xs:element ref="medical"/>
<xs:element ref="salary"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
This describes an element called root. In our example, this is (as the name suggests),
the root element of the document. Since this element contained more elements, it is defined as a
complex type (xs:complexType
). Inside this complex type, we can see it contains
some more elements: id
, details
, medical
and salary
.
These are not described as either a simple type or a complex type, neither do they have a name or any
other properties defined, as you might expect. Instead, they have the ref
attribute.
This means it is referring to a type defined elsewhere, called by the given name. However (and this
is what I mean by backwards), it has not been defined yet. The definitions for some follow after:
...
<xs:element name="id" type="xs:integer"/>
...
This defines the id
element which we have referred to above. It is a simple type
of the type integer. This is denoted by xs:integer
in the type
attribute.
The rest of the schema document follows pretty much the same format. However, several different data types are available, and there are also various attributes which can be applied to change the behaviour, for example allowing multiple occurances, or only one occurance.
XSD Data Types
Here are some links to the W3Schools pages on XSD data types.
Restrictions/Facets
XSD allows fine control over what values for elements are allowed, through use of restrictions, also known as facets. This can include things such as minimum and maximum values for numeric elements, and pattern matching and other restrictions for string types.
Some restriction examples (with brief explanations) are given below. Also, at the end of this section are some links to the W3Schools site to find out more.
<xs:element name="age">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="120"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
This example defines an element called age, which is of the integer type. Restrictions
have been used to only allow values between 0 and 120 (inclusive), by using the
xs:minInclusive
and xs:maxInclusive
elements, with appropriate values, inside
the xs:restriction
element. The base
attribute of this element defines what
type this element is derived from, or based on. This is all enclosed within a xs:simpleType
element, as this is a simple type, rather than a complex type.
<xs:element name="car">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Audi"/>
<xs:enumeration value="Volkswagen"/>
<xs:enumeration value="BMW"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
This example defines a type based on a string, which only allows one of a given set of values, either Audi, Volkswagen or BMW.
<xs:element name="initials">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z][a-zA-Z][a-zA-Z]"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
This example defines an element named initials which is again based on a string. However, this time the value must match the given pattern. In this case, it must contain exactly 3 characters, each of which must be an uppercase or lowercase letter (a to z).
There are many other ways in which the values can be restricted, and how various restrictions could be combined in order to refine the schema. To see more example like these, visit the W3Schools Restrictions/Facets page.