/** Recursively serialize a single element, appending it to DOM element <code>parent</code>. */
  protected void serializeElement(XMLStreamWriter writer, EventDataElement element)
      throws XMLStreamException {

    if (!element.isNull()) {
      // create a new node for the element and append it to the parent.
      String name = getXMLElementName(element.getName());

      if (element.isEmpty()) {
        writer.writeEmptyElement(name);
        // TODO: remove when stax bug is fixed.
        // this is a workaround for a bug in the 1.2 StAX implementation, where
        // if the only element in your document is empty, the closing "/>" never gets written.
        // any other API call fixes the problem, so here we do a no-op string append to force
        // the element closed.
        writer.writeCharacters(DUMMY_TEXT, 0, 0);
      } else {
        writer.writeStartElement(name);

        // add attributes for properties.
        Iterator<? extends Entry<String, Object>> props = element.iterateProperties();
        while (props.hasNext()) {
          Entry<String, Object> prop = props.next();
          Object value = prop.getValue();
          if (value != null) {
            String propName = getXMLElementName(prop.getKey());
            writer.writeAttribute(propName, value.toString());
          }
        }

        // add text to the element if applicable.
        String text = element.getText();
        if (text != null) writer.writeCharacters(text);

        // add child elements for children.
        Iterator<EventDataElement> children = element.iterateChildren();
        while (children.hasNext()) serializeElement(writer, children.next());
        writer.writeEndElement();
      }
    }
  }