Editing XML Schemas

An XML Schema describes the structure of an XML document and is used to validate XML document instances against it in order to check that the XML instance conforms to the specified requirements. If the XML instance conforms to the schema then it is said to be valid, otherwise it is invalid.

<oXygen/> has two pages dedicated to editing XML Schema: the usual Text page and the visual Design editor page.

 XML Schema Text Editor

This page presents the usual text view of an XML document synchronized in real time with an outline view. The outline view has two display modes: the standard outline mode and the components mode. To activate a side by side source and diagram presentation you have to enable the Show XML Schema Diagram checkbox from the Diagram preferences page.

 Special content completion features

The editor enhances the content completion of the XML editor inside the xs:annotation/xs:appinfo elements of an XML Schema with special support for the elements and attributes from a custom schema(by default ISO Schematron). This content completion enhancement can be configured from the XSD Content Completion preferences page.

If the current XML Schema schema imports or includes other XML Schema schemas then the global types and elements defined in the imported / included schemas are available in the content completion window together with the ones defined in the current file.

 

Figure 4.38. Schematron support in XML Schema content completion

Schematron support in XML Schema content completion

 References to XML Schema specification

The same as in editing XML documents, the message of an error obtained by validation of an XML Schema document includes a specification reference to the W3C specification for XML Schema. An error message contains an Info field that when clicked will open the browser on the "XML Schema Part 1:Structures" specification at exactly the point where the error is described thus allowing you to understand the reason for that error.

 

Figure 4.39. Link to specification for XML Schema errors

Link to specification for XML Schema errors

Validation of an XML Schema containing a type definition with a minOccurs or maxOccurs attribute having a value larger than 256 limits the value to 256 and issues a warning about this restriction in the Message panel at the bottom of the <oXygen/> window. Otherwise for large values of the minOccurs and maxOccurs attributes the validator fails with an OutOfMemory error which practically makes <oXygen/> unusable without a restart of the entire application.

[Important]Important

If the schema imports using only the namespace and without specifying the schema location and a catalog is set-up mapping the namespace to a certain location both validation and the schema components outline will correctly identify the imported schema.

 XML Schema actions

  • Document+SchemaShow definition (Ctrl + Shift + ENTER): Move the cursor to the definition of the referenced XML Schema item - element, group, simple or complex type. The same action is executed on a double click on a component name in the Schema Outline view. You can define a scope for this action in the same manner you define for Search Declarations

[Note]Note

The actions are available when the current editor is of XML Schema type.

 XML Schema editor specific actions

The list of actions specific for the XML Schema editor of <oXygen/> is:

  • Document+SchemaShow Definition (also available on the contextual menu of the editor panel) : move the cursor to the definition of the current element in this XSD schema.

 Flatten an XML Schema

If an XML Schema is organized on several levels linked by xs:include statements sometimes it is more convenient to work on the schema as a single flat file. To flatten schema <oXygen/> recursively adds included files to the master one. That means <oXygen/> replaces the xs:include elements with the ones coming from the included files.

This action works at file level not at schema document level so it is available only in Text mode of XML Schema editor. It can be accessed from the XML Schema text editor's contextual menu -> Refactoring -> Flatten Schema. Alternatively you can select one or more schemas in the Project view and invoke the action from the view's contextual menu. In this last case the feedback of the action will be presented in the Information view.

Schema flattening can also be accessed from the command line by running a command line the script, flattenSchema.bat on Windows or flattenSchema.sh on Mac OS X, Unix/Linux with the input file as the first argument and the output file as the second argument.

In the following example master.xsd includes slave.xsd. This, in turn, includes slave1.xsd which includes both slave2.xsd and slave3.xsd.

Listing of master.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="tns" xmlns:tns="tns" 
    xmlns:b="b" >
  <!-- included elements from slave.xsd -->
  <xs:include schemaLocation="slave.xsd"></xs:include>
  <!-- master.xsd -->
  <xs:element name="element1">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:element2" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>                  
                

Listing of slave.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="tns" xmlns:a="a" xmlns:b="b" 
    xmlns:c="c">
  <!-- included elements from slave1.xsd -->
  <xs:include schemaLocation="slave1.xsd"></xs:include>
  <!-- slave  -->
  <xs:element name="element2" xmlns:c="x"/>
</xs:schema>                  
                

Listing of slave1.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="tns" xmlns:tns="tns" 
    blockDefault=" restriction">
  <!-- included elements from slave2.xsd -->
  <xs:include schemaLocation="slave2.xsd"></xs:include>
  <!-- included elements from slave3.xsd -->
  <xs:include schemaLocation="slave3.xsd"></xs:include>
  <!-- slave1  -->
  <xs:element name="element0"/>
  <xs:element name="element7"/>    
  <xs:element name="element7Substitute" 
      substitutionGroup="tns:element7"  
      block="extension"/>
  <xs:element name="element6">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:element7"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="type1">
    <xs:sequence>
      <xs:element ref="tns:element0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
                

Listing of slave2.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="tns" 
  xmlns:tns="tns"
  elementFormDefault="qualified" 
  attributeFormDefault="qualified">
  <!-- slave2 -->
  <xs:element name="a"></xs:element>
  <a:element name="element9" 
        xmlns:a="http://www.w3.org/2001/XMLSchema">
    <xs:complexType>
      <xs:sequence>
        <!-- This element is from the target namespace -->
        <xs:element name="element3" 
              xmlns:b="http://www.w3.org/2001/XMLSchema"/>
        <!-- Element from no namespace -->
        <xs:element name="element4" form="unqualified"/>
        <a:element ref="tns:a"></a:element>
      </xs:sequence>
      <!-- Attribute from the target namespace -->
      <b:attribute name="attr1" type="xs:string" 
            xmlns:b="http://www.w3.org/2001/XMLSchema"/>
      <!-- Attribute from the no namespace -->
      <xs:attribute name="attr2" type="xs:string" 
            form="unqualified"/>
    </xs:complexType>        
  </a:element>
</xs:schema>                  
                

Listing of slave3.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="tns" finalDefault="restriction" 
    xmlns:tns="tns">
  <!-- slave3 -->
  <xs:complexType name="ct1"/>
  <xs:complexType name="ct2" final="extension">
    <xs:complexContent>
      <xs:extension base="tns:ct1"/>
    </xs:complexContent>
  </xs:complexType>
  <xs:simpleType name="st1" final="union">
    <xs:restriction base="xs:integer"/>
  </xs:simpleType>
  <xs:simpleType name="st2" final="union">
    <xs:restriction base="tns:st1">
      <xs:enumeration value="1"/>
      <xs:enumeration value="2"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="e1" type="tns:c1" final="restriction"/>
  <xs:element name="e2ext" type="tns:c2" 
        substitutionGroup="tns:e1"></xs:element>
  <xs:complexType name="c1">
    <xs:sequence>
      <xs:element ref="tns:e1"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="c2">
    <xs:complexContent>
      <xs:extension base="tns:c1">
        <xs:sequence>
          <xs:element ref="tns:e1"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>                  
                

Listing of master.xsd after it has been flattened

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="tns" xmlns:a="a" 
      xmlns:b="b" xmlns:c="c" xmlns:tns="tns"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!-- included elements from slave.xsd -->
  <!-- included elements from slave1.xsd -->
  <!-- included elements from slave2.xsd -->
  <!-- slave2 -->
  <xs:element block="restriction" name="a"/>
  <a:element block="restriction" name="element9" 
        xmlns:a="http://www.w3.org/2001/XMLSchema">
    <xs:complexType>
      <xs:sequence>
        <!-- This element is from the target namespace -->
        <xs:element block="restriction" form="qualified" name="element3"
          xmlns:b="http://www.w3.org/2001/XMLSchema"/>
        <!-- Element from no namespace -->
        <xs:element block="restriction" form="unqualified" 
              name="element4"/>
        <a:element ref="tns:a"/>
      </xs:sequence>
      <!-- Attribute from the target namespace -->
      <b:attribute form="qualified" name="attr1" type="xs:string"
        xmlns:b="http://www.w3.org/2001/XMLSchema"/>
      <!-- Attribute from the no namespace -->
      <xs:attribute form="unqualified" name="attr2" type="xs:string"/>
    </xs:complexType>
  </a:element>
  <!-- included elements from slave3.xsd -->
  <!-- slave3 -->
  <xs:complexType block="restriction" final="restriction" name="ct1"/>
  <xs:complexType block="restriction" final="extension" name="ct2">
    <xs:complexContent>
      <xs:extension base="tns:ct1"/>
    </xs:complexContent>
  </xs:complexType>
  <xs:simpleType final="union" name="st1">
    <xs:restriction base="xs:integer"/>
  </xs:simpleType>
  <xs:simpleType final="union" name="st2">
    <xs:restriction base="tns:st1">
      <xs:enumeration value="1"/>
      <xs:enumeration value="2"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element block="restriction" final="restriction" name="e1" 
        type="tns:c1"/>
  <xs:element block="restriction" final="restriction" name="e2ext" 
        substitutionGroup="tns:e1"
    type="tns:c2"/>
  <xs:complexType block="restriction" final="restriction" 
        name="c1">
    <xs:sequence>
      <xs:element ref="tns:e1"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType block="restriction" final="restriction" 
        name="c2">
    <xs:complexContent>
      <xs:extension base="tns:c1">
        <xs:sequence>
          <xs:element ref="tns:e1"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <!-- slave1  -->
  <xs:element block="restriction" name="element0"/>
  <xs:element block="restriction" name="element7"/>
  <xs:element block="extension" name="element7Substitute" 
        substitutionGroup="tns:element7"/>
  <xs:element block="restriction" name="element6">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:element7"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType block="restriction" name="type1">
    <xs:sequence>
      <xs:element ref="tns:element0"/>
    </xs:sequence>
  </xs:complexType>
  <!-- slave  -->
  <xs:element name="element2" xmlns:c="x"/>
  <!-- master.xsd -->
  <xs:element name="element1">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="tns:element2"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
                

The case of XML Schema redefinitions is also handled as the example below shows.

Listing of master.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:redefine schemaLocation="slave1.xsd">
    <xs:complexType name="tp">
      <xs:complexContent>
        <xs:extension base="tp">
          <xs:choice>
            <xs:element name="el2" type="xs:NCName"/>
            <xs:element name="el3" type="xs:string"/>
          </xs:choice>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
  <xs:element name="el" type="tp"/>
</xs:schema>
                

Listing of slave1.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:redefine schemaLocation="slave2.xsd">
    <xs:complexType name="tp">
      <xs:complexContent>
        <xs:extension base="tp">
          <xs:attribute name="a"/>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
</xs:schema>
                

Listing of slave2.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="tp">
    <xs:sequence>
      <xs:element name="el" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
                

Listing of master.xsd after it has been flattened>

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:complexType name="tp">
    <xs:complexContent>
      <xs:extension base="tp_Redefined1">
        <xs:choice>
          <xs:element name="el2" type="xs:NCName"/>
          <xs:element name="el3" type="xs:string"/>
        </xs:choice>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="tp_Redefined1">
    <xs:complexContent>
      <xs:extension base="tp_Redefined0">
        <xs:attribute name="a"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="tp_Redefined0">
    <xs:sequence>
      <xs:element name="el" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="el" type="tp"/>
</xs:schema>
                

The references to the included schema files can be resolved through an XML Catalog.