protected Element readActionRequestElement(
      Element bodyElement, ActionRequestMessage message, ActionInvocation actionInvocation) {
    NodeList bodyChildren = bodyElement.getChildNodes();

    log.fine(
        "Looking for action request element matching namespace:" + message.getActionNamespace());

    for (int i = 0; i < bodyChildren.getLength(); i++) {
      Node bodyChild = bodyChildren.item(i);

      if (bodyChild.getNodeType() != Node.ELEMENT_NODE) continue;

      String unprefixedName = getUnprefixedNodeName(bodyChild);
      if (unprefixedName.equals(actionInvocation.getAction().getName())) {
        if (bodyChild.getNamespaceURI() == null
            || !bodyChild.getNamespaceURI().equals(message.getActionNamespace()))
          throw new UnsupportedDataException(
              "Illegal or missing namespace on action request element: " + bodyChild);
        log.fine("Reading action request element: " + unprefixedName);
        return (Element) bodyChild;
      }
    }
    throw new UnsupportedDataException(
        "Could not read action request element matching namespace: "
            + message.getActionNamespace());
  }
  public void writeBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation)
      throws UnsupportedDataException {

    log.fine("Writing body of " + requestMessage + " for: " + actionInvocation);

    try {

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setNamespaceAware(true);
      Document d = factory.newDocumentBuilder().newDocument();
      Element body = writeBodyElement(d);

      writeBodyRequest(d, body, requestMessage, actionInvocation);

      if (log.isLoggable(Level.FINER)) {
        log.finer(
            "===================================== SOAP BODY BEGIN ============================================");
        log.finer(requestMessage.getBodyString());
        log.finer(
            "-===================================== SOAP BODY END ============================================");
      }

    } catch (Exception ex) {
      throw new UnsupportedDataException("Can't transform message payload: " + ex, ex);
    }
  }
  public void readBody(ActionRequestMessage requestMessage, ActionInvocation actionInvocation)
      throws UnsupportedDataException {

    log.fine("Reading body of " + requestMessage + " for: " + actionInvocation);
    if (log.isLoggable(Level.FINER)) {
      log.finer(
          "===================================== SOAP BODY BEGIN ============================================");
      log.finer(requestMessage.getBodyString());
      log.finer(
          "-===================================== SOAP BODY END ============================================");
    }

    String body = getMessageBody(requestMessage);
    try {

      DocumentBuilderFactory factory = createDocumentBuilderFactory();
      factory.setNamespaceAware(true);
      DocumentBuilder documentBuilder = factory.newDocumentBuilder();
      documentBuilder.setErrorHandler(this);

      Document d = documentBuilder.parse(new InputSource(new StringReader(body)));

      Element bodyElement = readBodyElement(d);

      readBodyRequest(d, bodyElement, requestMessage, actionInvocation);

    } catch (Exception ex) {
      throw new UnsupportedDataException("Can't transform message payload: " + ex, ex, body);
    }
  }
  protected void writeBodyRequest(
      Document d,
      Element bodyElement,
      ActionRequestMessage message,
      ActionInvocation actionInvocation)
      throws Exception {

    Element actionRequestElement =
        writeActionRequestElement(d, bodyElement, message, actionInvocation);
    writeActionInputArguments(d, actionRequestElement, actionInvocation);
    message.setBody(toString(d));
  }
  protected Element writeActionRequestElement(
      Document d,
      Element bodyElement,
      ActionRequestMessage message,
      ActionInvocation actionInvocation) {

    log.fine("Writing action request element: " + actionInvocation.getAction().getName());

    Element actionRequestElement =
        d.createElementNS(
            message.getActionNamespace(), "u:" + actionInvocation.getAction().getName());
    bodyElement.appendChild(actionRequestElement);

    return actionRequestElement;
  }