Dexterity XML
=============

**A reference for Dexterity's XML name spaces**

Introduction
------------

The schema (structure) of a Dexterity content type may be detailed in two very
different ways:

    * In Python as a Zope schema; or,

    * In XML

When you are using Dexterity's through-the-web schema editor, all your work is
being saved in the content type's Factory Type Information (FTI) as XML.
``plone.supermodel`` dynamically translates that XML into Python objects which
are used to display and edit your content objects.

The XML model of your content object may be exported from Dexterity and
incorporated into a Python package. That's typically done with code like::

    class IExampleType(form.Schema):

        form.model("models/example_type.xml")

or::

    from plone.supermodel import xmlSchema

    IExampleType = xmlSchema("models/example_type.xml")

XML models in a package may be directly edited. (Dexterity will probably also
include a TTW XML-model editor at some point in the future.)

This document is a reference to the tags and attributes you may use in model
XML files. This includes several form-control and security-control attributes
that are not available through the TTW schema editor.

XML Document Structure
----------------------

Dexterity requires that its model XML be well-formed XML, including name space
declarations. The typical structure of a Dexterity XML document is::

    <?xml version="1.0" encoding="UTF-8"?>
    <model xmlns="http://namespaces.plone.org/supermodel/schema"
           xmlns:form="http://namespaces.plone.org/supermodel/form"
           xmlns:security="http://namespaces.plone.org/supermodel/security">
        <schema>
            <field type="zope.schema.TextLine" name="one"
                <title>One</title>
                ... More field attributes
            </field>
            ... More fields
        </schema>
    </model>

Only the default name space (.../supermodel/schema) is required for basic
schema. The ``supermodel/form`` and ``supermodel/schema`` provide additional
attributes to control form presentation and security.

supermodel/schema fields
------------------------

Most of the supermodel/schema field tag and its attributes map directly to what's available via the TTW schema editor::

        <field name="dummy" type="zope.schema.TextLine">
          <default>abc</default>
          <description>Test desc</description>
          <max_length>10</max_length>
          <min_length>2</min_length>
          <missing_value>m</missing_value>
          <readonly>True</readonly>
          <required>False</required>
          <title>Test</title>
        </field>

The field ``type`` needs to be the full dotted name (as if it was being
imported in Python) of the field type.

Fieldsets
~~~~~~~~~

It's easy to add fieldsets by surrounding embedding fields tags in a ``fieldset`` block::

      <schema>
        ...
        <fieldset name="test"
                label="Test Fieldset"
                description="Description of test fieldset">
            <field name="three" type="zope.schema.TextLine">
              <description/>
              <title>Three</title>
            </field>
            <field name="four" type="zope.schema.TextLine">
              <description/>
              <title>Four</title>
            </field>
        </fieldset>
        ...
      </schema>


Vocabularies
~~~~~~~~~~~~

Vocabularies may be specified via dotted names using the ``source`` tag::

    <field name="dummy" type="zope.schema.Choice">
        <default>a</default>
        <description>Test desc</description>
        <missing_value/>
        <readonly>True</readonly>
        <required>False</required>
        <title>Test</title>
        <source>plone.supermodel.tests.dummy_vocabulary_instance</source>
    </field>

Where the full Python dotted-name of a Zope vocabulary in a package::

    from zope.schema.vocabulary import SimpleVocabulary

    dummy_vocabulary_instance = SimpleVocabulary.fromItems([(1, 'a'), (2, 'c')])

Or, a source binder::

    <field name="dummy" type="zope.schema.Choice">
        ...
        <source>plone.supermodel.tests.dummy_binder</source>
    </field>


With Python like::

    from zope.schema.interfaces import IContextSourceBinder

    class Binder(object):
        implements(IContextSourceBinder)

        def __call__(self, context):
            return SimpleVocabulary.fromValues(['a', 'd', 'f'])

    dummy_binder = Binder()

You may also use the ``vocabulary`` tag rather than ``source`` to refer to named vocabularies registered via the ZCA.


Internationalization
~~~~~~~~~~~~~~~~~~~~

Translation domains and message ids can be specified for text
that is interpreted as unicode. This will result in deserialization
as a zope.i18nmessageid message id rather than a basic Unicode string.

Note that we need to add the i18n namespace and a domain specification::

    <model xmlns="http://namespaces.plone.org/supermodel/schema"
           xmlns:i18n="http://xml.zope.org/namespaces/i18n"
           i18n:domain="your.application">
        <schema>

            <field type="zope.schema.TextLine" name="title">
                <title i18n:translate="yourapp_test_title">Title</title>
            </field>

        </schema>
    </model>


supermodel/form attributes
--------------------------

supermodel/form provides attributes that govern presentation and editing.

after/before
~~~~~~~~~~~~

To re-order fields, use ``form:after`` or ``form:before``.

The value should be either ``'*'``, to put the field first/last in the form,
or the name of a another field. Use ``'.fieldname'`` to refer to field in the
current schema (or a base schema). Use a fully prefixed name (e.g.
``'my.package.ISomeSchema'``) to refer to a field in another schema. Use an
unprefixed name to refer to a field in the default schema for the form.

Example::

    <field type="zope.schema.TextLine"
           name="one"
           form:after="two">
        <title>One</title>
    </field>

mode
~~~~

To turn a field into a view mode or hidden field, use ``form:mode``.  The
mode may be set for only some forms by specifying a form interface in the
same manner as for ``form:omitted``.

Example::

    <field type="zope.schema.TextLine"
            name="three"
            form:mode="z3c.form.interfaces.IEditForm:input">
        <title>Three</title>
    </field>


omitted
~~~~~~~

To omit a field from all forms, use ``form:omitted="true"``.  To omit a field
only from some forms, specify a form interface like
``form:omitted="z3c.form.interfaces.IForm:true"``. Multiple interface:value
settings may be specified, separated by spaces.

Examples::

    <field type="zope.schema.TextLine"
           name="one"
           form:omitted="true">
        <title>One</title>
    </field>

    <field type="zope.schema.TextLine" name="three"
            form:omitted="z3c.form.interfaces.IForm:true z3c.form.interfaces.IEditForm:false"
            >
        <title>Three</title>
    </field>

The latter example hides the field on everything except the edit form.


widget
~~~~~~

To set a custom widget for a field, use ``form:widget`` to give a fully
qualified name to the field widget factory.

Example::

    <field type="zope.schema.TextLine"
           name="password"
           form:widget="z3c.form.browser.password.PasswordFieldWidget">
        <title>One</title>
    </field>


Dynamic Defaults
~~~~~~~~~~~~~~~~

To set a dynamic default for a field, use a ``defaultFactory`` tag to
give a fully qualified name for a callable. The defaultFactory callable must
provide either plone.supermodel.interfaces.IDefaultFactory or
zope.schema.interfaces.IContextAwareDefaultFactory.

Example::

    <field type="zope.schema.TextLine" name="three">
        <title>Three</title>
        <defaultFactory>plone.supermodel.tests.dummy_defaultFactory</defaultFactory>
    </field>

Sample Python for the validator factory::

    @provider(IDefaultFactory)
    def dummy_defaultFactory():
        return u'something'

For a callable using context::

    @provider(IContextAwareDefaultFactory)
    def dummy_defaultCAFactory(context):
        return context.something

.. note::

    The ``defaultFactory`` tag was added in plone.supermodel 1.2.3,
    shipping with Plone 4.3.2+.


validator
~~~~~~~~~

To set a custom validator for a field, use ``form:validator`` to give a fully
qualified name to the field validator factory. The validator factory should be
a class derived from one of the validators in z3c.form.validator.

Example::

    <field type="zope.schema.TextLine"
            name="three"
            form:validator="plone.autoform.tests.test_utils.TestValidator">
        <title>Three</title>
    </field>

Sample Python for the validator factory::

    class TestValidator(z3c.form.validator.SimpleFieldValidator):

        def validate(self, value):
            super(TestValidator, self).validate(value)
            raise Invalid("Test")

.. _dexterity-xml-security:

supermodel/security attributes
------------------------------

read-permission/write-permission
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To set a read or write permission, use ``security:read-permission`` or
``security:write-permission``. The value should be the name of an
``IPermission`` utility.

Example::

    <field type="zope.schema.TextLine"
            name="one"
            security:read-permission="zope2.View"
            security:write-permission="cmf.ModifyPortalContent">
        <title>One</title>
    </field>
