@Override
  public void unmarshal(Element root) throws ParseException {
    // attributes
    NamedNodeMap attrs = root.getAttributes();
    for (int i = 0; i < attrs.getLength(); i++) {
      Attr attr = (Attr) attrs.item(i);
      String name = attr.getName();
      String value = attr.getNodeValue();
      if (name.equals("version")) {
        version = value;
        break;
      }
    }

    // elements
    ArrayList<Element> children = (ArrayList<Element>) DOMHelp.getChildElements(root);
    for (Element child : children) {
      String localName = child.getLocalName();
      if (localName.equals("event")) {
        PremisEvent ev = new PremisEvent();
        ev.unmarshal(child);
        getEvent().add(ev);
      } else if (localName.equals("object")) {
        String typeString = child.getAttributeNS(NS.XSI.ns(), "type").replaceAll("^\\w+:", "");
        PremisObjectType type = PremisObject.PremisObjectType.valueOf(typeString);
        if (type == null) {
          continue;
        }
        PremisObject obj = new PremisObject(type);
        obj.unmarshal(child);
        getObject().add(obj);
      } else if (localName.equals("agent")) {
        PremisAgent agent = new PremisAgent();
        agent.unmarshal(child);
        getAgent().add(agent);
      } else if (localName.equals("rights")) {
        PremisRights r = new PremisRights();
        r.unmarshal(child);
        getRights().add(r);
      }
    }
  }
  @Override
  public void marshal(Element root, Document doc) {

    // set up namespace declarations and schema references
    root.setAttributeNS(NS.XMLNS.ns(), "xmlns:premis", NS.PREMIS.ns());
    root.setAttributeNS(NS.XMLNS.ns(), "xmlns:xlink", NS.XLINK.ns());
    root.setAttributeNS(NS.XMLNS.ns(), "xmlns:xsi", NS.XSI.ns());
    root.setAttributeNS(NS.XSI.ns(), "xsi:schemaLocation", NS.PREMIS.schemaLoc());

    if (version != null && !version.isEmpty()) {
      root.setAttribute("version", version);
    } else {
      root.setAttribute("version", "2.2");
    }
    // sequence is important!
    for (PremisObject object : getObject()) {
      Element objectE = doc.createElementNS(NS.PREMIS.ns(), "premis:object");
      object.marshal(objectE, doc);
      root.appendChild(objectE);
    }
    for (PremisEvent event : getEvent()) {
      Element eventE = doc.createElementNS(NS.PREMIS.ns(), "premis:event");
      event.marshal(eventE, doc);
      root.appendChild(eventE);
    }
    for (PremisAgent agent : getAgent()) {
      Element agentE = doc.createElementNS(NS.PREMIS.ns(), "premis:agent");
      agent.marshal(agentE, doc);
      root.appendChild(agentE);
    }
    for (PremisRights rights : getRights()) {
      Element rightsE = doc.createElementNS(NS.PREMIS.ns(), "premis:rights");
      rights.marshal(rightsE, doc);
      root.appendChild(rightsE);
    }
  }