Dexterity fields

xmldirector.plonecore comes with the following Dexterity fields that can be either used programmatically in your own field schema or through-the-web.

Example of a simple Dexterity-based content-type using all available fields:

from zope.interface import implements
from plone.dexterity.content import Item
from plone.supermodel import model

from xmldirector.plonecore.i18n import MessageFactory as _

from xmldirector.plonecore.dx import dexterity_base
from xmldirector.plonecore.dx.xml_binary import XMLBinary
from xmldirector.plonecore.dx.xml_image import XMLImage
from xmldirector.plonecore.dx.xml_field import XMLText
from xmldirector.plonecore.dx.xpath_field import XMLXPath


class IXMLDocument(model.Schema):

    xml_content = XMLText(
        title=_(u'XML Content'),
        required=False
    )

    xml_xpath = XMLXPath(
        title=_(u'XML XPath expression'),
        description=_(u'Format: field=<fieldname>,xpath=<xpath expression>'),
        required=False
    )

    xml_binary = XMLBinary(
        title=_(u'XML Binary'),
        required=False
    )

    xml_image = XMLImage(
        title=_(u'XML Image'),
        required=False
    )


class XMLDocument(Item, dexterity_base.Mixin):

    implements(IXMLDocument)

XMLText

The XMLText can be used to store valid XML content. The field is rendered without Plone using the ACE editor. You can perform a client-side XML validation within the edit mode of a document by clicking on the Validate XML button. A document with invalid XML content can not be submitted or saved. Invalid XML will be rejected with an error message through the edit form.

XMLXPath

The XMLXPath field can be used to reference an XMLText field in order to display a part of the XML content using an XPath expression.

Example

An XMLPath field with field name myxml might contain the following XML content:

<?xml version="1.0"?>
<doc>
    <metadata>
        <title>This is a text</title>
    </metdata>
    <body>....</body>
</doc>

In order to extract and display the <title> text within a dedicated Dexterity field you can use the following extended expression:

field=<fieldname>,xpath=<xpath expression>

In this case you would use:

field=myxml,xpath=/doc/metadata/title/text()

Note that the current syntax is very rigid and does not allow any whitespace characters expect within the <xpath expression>.

XMLBinary, XMLImage

Same as file and image field in Plone but with BaseX or eXist-db as storage layer.

API for setting and getting XML field values

The values of XML fields are managed through dedicated API methods xml_get() and xml_set(). This is inconsistent with the standard Dexterity approach to set/get directly on the objects or through behaviors. Unfortunately Dexterity has no concept of a storage layer and in order to provide a consistent and explicit API it was necessary to invent our own API for the XML fields of xmldirector.plonecore.

Manipulating XMLText fields

Storing XML data and retriving is pretty trivial. And XML string to be stored must be either given as UTF-8 encoded byte string or as Python unicode string (without the XML premable):

xml = """<xml? version="1.0"?>
         <example>data</example>
      """
# Store XML
my_doc.xml_set('xml_content', xml)

# Read XML
xml2 = my_doc.xml_get('xml_content')

Manipulating XMLPath fields

The following example shows how to retrieve parts of an XML document through an XPath field:

xml = "<xml? version="1.0"?>
         <example>
            <title>Hello world/title>
            <value>a</value>
            <value>b</value>
            <value>c</value>
         </example>
      "

# Store XML
my_doc.xml_set('xml_content', xml)

# Create an Xpath expression for the retrieving the title
my_doc.xml_set('xml_xpath', 'field=xml_content,xpath=//title/text()')
result = my_doc.xml_get('xml_xpath)
# result = [u'Hello world']

# Create an Xpath expression for all <value> values
my_doc.xml_set('xml_xpath', 'field=xml_content,xpath=//value/text()')
result = my_doc.xml_get('xml_xpath)
# result = [u'a', u'b', u'c']

Manipulating XMLImage fields

For storing image data on an XMLImage field, the image data must be encapsulated as an instance of plone.namedfile.NamedImage:

from plone.namedfile import NamedImage

# storing image data
named_image = NamedImage()
named_image.data = img_data
named_image.filename = u'test.jpg'
named_image.contentType = 'image/jpg'
my_doc.xml_set('xml_image', named_image)

# retrieving image data
result = my_doc.xml_get('xml_image')
img_data = result.data            # binary image data
filename = result.filename        # 'test.jpg'
mimetype = result.contentType     # 'image/jpg'

Manipulating XMLBinary fields

For storing binary data on an XMLBinary field, the binary data must be encapsulated as an instance of plone.namedfile.NamedFile:

from plone.namedfile import NamedFile

# storing image data
named_file= NamedFile()
named_file.data = file_data
named_file.filename = u'some.pdf'
named_file.contentType = 'application/pdf'
my_doc.xml_set('xml_binary', named_file)

# retrieving binary data
result = my_doc.xml_get('xml_binary')
img_data = result.data            # binary data
filename = result.filename        # 'some.pdf'
mimetype = result.contentType     # 'application/pdf'