@Override
 protected void writeNsDecl(String prefix, String namespaceURI) throws XMLStreamException {
   if (namespaceDeclarations) {
     try {
       if (!getScope().getInfo().startObjectWritten) {
         target.startObject();
         getScope().getInfo().startObjectWritten = true;
       }
       if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
         target.name('@' + XMLConstants.XMLNS_ATTRIBUTE);
       } else {
         target.name('@' + XMLConstants.XMLNS_ATTRIBUTE + namespaceSeparator + prefix);
       }
       target.value(namespaceURI);
     } catch (IOException e) {
       throw new XMLStreamException("Cannot write namespace declaration: " + namespaceURI, e);
     }
   }
 }
 public void writeStartArray(String fieldName) throws XMLStreamException {
   if (autoEndArray && getScope().getInfo().isArray()) {
     writeEndArray();
   }
   getScope().getInfo().startArray(fieldName);
   getScope().getInfo().pendingStartArray = false;
   try {
     if (!getScope().getInfo().startObjectWritten) {
       target.startObject();
       getScope().getInfo().startObjectWritten = true;
     }
     target.name(fieldName);
     target.startArray();
   } catch (IOException e) {
     throw new XMLStreamException("Cannot start array: " + fieldName, e);
   }
 }
 @Override
 protected void writeAttr(String prefix, String localName, String namespaceURI, String value)
     throws XMLStreamException {
   String name =
       XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)
           ? localName
           : prefix + namespaceSeparator + localName;
   try {
     if (!getScope().getInfo().startObjectWritten) {
       target.startObject();
       getScope().getInfo().startObjectWritten = true;
     }
     target.name('@' + name);
     target.value(value);
   } catch (IOException e) {
     throw new XMLStreamException("Cannot write attribute: " + name, e);
   }
 }
 @Override
 protected ScopeInfo writeStartElementTag(String prefix, String localName, String namespaceURI)
     throws XMLStreamException {
   ScopeInfo parentInfo = getScope().getInfo();
   if (parentInfo.hasData()) {
     if (!skipSpace || !isWhitespace(parentInfo.getData())) {
       throw new XMLStreamException(
           "Mixed content is not supported: '" + parentInfo.getData() + "'");
     }
     parentInfo.setData(null);
   }
   String fieldName = getFieldName(prefix, localName);
   if (getScope().isRoot() && getScope().getLastChild() != null && !documentArray) {
     if (!fieldName.equals(parentInfo.getArrayName())) {
       throw new XMLStreamException("Multiple roots within document");
     }
   }
   if (parentInfo.pendingStartArray) {
     writeStartArray(fieldName);
   }
   try {
     if (!parentInfo.isArray()) {
       if (!parentInfo.startObjectWritten) {
         target.startObject();
         parentInfo.startObjectWritten = true;
       }
     } else if (autoEndArray && !fieldName.equals(parentInfo.getArrayName())) {
       writeEndArray();
     }
     if (!parentInfo.isArray()) {
       target.name(fieldName);
     } else {
       parentInfo.incArraySize();
     }
   } catch (IOException e) {
     throw new XMLStreamException("Cannot write start element: " + fieldName, e);
   }
   return new ScopeInfo();
 }
 @Override
 protected void writeEndElementTag() throws XMLStreamException {
   try {
     if (getScope().getInfo().hasData()) {
       if (getScope().getInfo().startObjectWritten) {
         target.name("$");
       }
       target.value(getScope().getInfo().getData());
     }
     if (autoEndArray && getScope().getInfo().isArray()) {
       writeEndArray();
     }
     if (getScope().getInfo().startObjectWritten) {
       target.endObject();
     } else if (!getScope().getInfo().hasData()) {
       target.value(null);
     }
   } catch (IOException e) {
     throw new XMLStreamException(
         "Cannot write end element: "
             + getFieldName(getScope().getPrefix(), getScope().getLocalName()),
         e);
   }
 }