@Override
 public void endElement(final String uri, final String localName, final String name)
     throws SAXException {
   if (start) {
     level--;
     try {
       pushcontentWriter.writeEndElement();
     } catch (XMLStreamException e) {
       throw new SAXException(e);
     }
   }
   if (level == 0) {
     // turn off start if we reach the end tag of staring element
     start = false;
     if (ATTR_CONACTION_VALUE_PUSHAFTER.equals(pushType)
         || ATTR_CONACTION_VALUE_PUSHREPLACE.equals(pushType)) {
       // if it is pushafter or replace, we need to record content in pushtable
       // if target == null we have already reported error in startElement;
       if (target != null) {
         if (pushcontentWriter != null) {
           try {
             pushcontentWriter.close();
           } catch (final XMLStreamException e) {
             throw new SAXException(e);
           }
         }
         addtoPushTable(target, pushcontentDocumentFragment, pushType);
         pushcontentWriter = getXMLStreamWriter();
         target = null;
         pushType = null;
       }
     }
   }
 }
  @Override
  public void startElement(
      final String uri, final String localName, final String name, final Attributes atts)
      throws SAXException {
    if (start) {
      // if start is true, we need to record content in pushcontent
      // also we need to add level to make sure start is turn off
      // at the corresponding end element
      level++;
      putElement(name, atts, false);
    }

    final String conactValue = atts.getValue(ATTRIBUTE_NAME_CONACTION);
    if (!start && conactValue != null) {
      if (ATTR_CONACTION_VALUE_PUSHBEFORE.equals(conactValue)) {
        if (pushcontentDocumentFragment.getChildNodes().getLength() != 0) {
          // there are redundant "pushbefore", create a new pushcontent and emit a warning message.
          if (pushcontentWriter != null) {
            try {
              pushcontentWriter.close();
            } catch (final XMLStreamException e) {
              throw new SAXException(e);
            }
          }
          pushcontentWriter = getXMLStreamWriter();
          logger.warn(
              MessageUtils.getInstance().getMessage("DOTJ044W").setLocation(atts).toString());
        }
        start = true;
        level = 1;
        putElement(name, atts, true);
        pushType = ATTR_CONACTION_VALUE_PUSHBEFORE;
      } else if (ATTR_CONACTION_VALUE_PUSHAFTER.equals(conactValue)) {
        start = true;
        level = 1;
        if (target == null) {
          logger.error(
              MessageUtils.getInstance().getMessage("DOTJ039E").setLocation(atts).toString());
        } else {
          putElement(name, atts, true);
          pushType = ATTR_CONACTION_VALUE_PUSHAFTER;
        }
      } else if (ATTR_CONACTION_VALUE_PUSHREPLACE.equals(conactValue)) {
        start = true;
        level = 1;
        target = toURI(atts.getValue(ATTRIBUTE_NAME_CONREF));
        if (target == null) {
          logger.error(
              MessageUtils.getInstance().getMessage("DOTJ040E").setLocation(atts).toString());
        } else {
          pushType = ATTR_CONACTION_VALUE_PUSHREPLACE;
          putElement(name, atts, true);
        }

      } else if (ATTR_CONACTION_VALUE_MARK.equals(conactValue)) {
        target = toURI(atts.getValue(ATTRIBUTE_NAME_CONREF));
        if (target == null) {
          logger.error(
              MessageUtils.getInstance().getMessage("DOTJ068E").setLocation(atts).toString());
        }
        if (target != null
            && pushcontentDocumentFragment != null
            && pushcontentDocumentFragment.getChildNodes().getLength() > 0
            && ATTR_CONACTION_VALUE_PUSHBEFORE.equals(pushType)) {
          // pushcontent != null means it is pushbefore action
          // we need to add target and content to pushtable
          if (pushcontentWriter != null) {
            try {
              pushcontentWriter.close();
            } catch (final XMLStreamException e) {
              throw new SAXException(e);
            }
          }
          addtoPushTable(target, replaceContent(pushcontentDocumentFragment), pushType);
          pushcontentWriter = getXMLStreamWriter();
          target = null;
          pushType = null;
        }
      }
    } // else if (pushcontent != null && pushcontent.length() > 0 && level == 0) {
    // if there is no element with conaction="mark" after
    // one with conaction="pushbefore", report syntax error

    // }
  }