1 Reply Latest reply: Aug 16, 2012 11:27 AM by 929890 RSS

    Handling empty elements with XMLStreamReader and XMLStreamWriter

    929890
      I want an XMLStreamReader to read an XML document and write it out with an XMLStreamWriter which basically works well.
      But there is one problem:
      The XML document may contain empty elements in both ways:
      *<myElem/>* and *<myElem></myElem>*
      XMLStreamReader splits an empty element in two events: START_ELEMENT followed by an END_ELEMENT event.

      How can I ensure that the outputted document is equal to the parsed XML document so that an <myElem/> is not written as <myElem></myElem>?

      Even more it may be that an empty element has attributes. How can I ensure that these attributes will be written? Using XMLStreamWriter.writeEmptyElement(elementName) seems not to support writing attributes of an empty element.

      In fact I want to detect special empty elements with a particular name attribute to NOT write them out in the new XML document.

      in XML document:
      <string name="myAttrib"/> <-- to be cut off
      .
      .
      .
      <string name="myAttrib">XXX</name> <-- shall remain

      shall not be written to the target XML document.
        • 1. Re: Handling empty elements with XMLStreamReader and XMLStreamWriter
          929890
          Okay.
          Here is how I solved it by myself:
          private void removeEmptyDbReference(InputStream is) throws SQLException, XMLStreamException, IOException {
          //is.mark(0);
          //ByteArrayOutputStream baos = new ByteArrayOutputStream();
          //byte[] buf = new byte[1024];
          //int byteRead = 0;
          //while( (byteRead = is.read(buf)) != -1 ){
          //     baos.write(buf, 0, byteRead);
          //}
          //baos.flush();
          //System.out.println(baos);
          //is.reset();
          //baos.close();
               XMLInputFactory input = XMLInputFactory.newInstance();
               XMLStreamReader reader = input.createXMLStreamReader(is, "UTF-8");
          
               XMLOutputFactory output = XMLOutputFactory.newInstance();
               OutputStream out = new ByteArrayOutputStream();
               XMLStreamWriter writer = output.createXMLStreamWriter(out, "UTF-8");
          
               int event = reader.getEventType();
          
               boolean dbRefFound = false;
               boolean emptyDbRefFound = false;
               int lastEventType = -1;
               String elementname = null;
               HashMap<String, String> elementAttribs = new HashMap<String, String>();
               while (reader.hasNext()) {
                    switch (event) {
                    case XMLStreamConstants.START_ELEMENT:
                         if( elementname != null ){
                              writer.writeStartElement(elementname);
                              Set<Entry<String, String>> meSet = elementAttribs.entrySet();
                              for( Entry<String, String> me : meSet ){
                                   writer.writeAttribute(me.getKey(), me.getValue());
                              }//end for me
                         }
                              
                         elementname = reader.getName().getLocalPart();
                         for( int i=0; i<reader.getAttributeCount(); i++ ){
                              elementAttribs.put(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
                         }//end for i
                              
                         if( elementname.equals("string") 
                              && reader.getAttributeValue(null, "name") != null 
                              && reader.getAttributeValue(null, "name").equals("DbReference") ){
                                   dbRefFound = true;
                         }
                         break;
                    case XMLStreamConstants.END_ELEMENT:
                         if( lastEventType == XMLStreamConstants.CHARACTERS  &&  dbRefFound ){
                              writer.writeEndElement();
                              dbRefFound = false;
                              elementname = null;
                              elementAttribs.clear();
                              break;
                         }
                         if( lastEventType == XMLStreamConstants.START_ELEMENT  &&  dbRefFound ) {
                              elementname = null;
                              elementAttribs.clear();
                              dbRefFound = false;
                              emptyDbRefFound = true;
                              break;
                         }
                         // empty element
                         if( lastEventType == XMLStreamConstants.START_ELEMENT  &&  !dbRefFound ) {
                              writer.writeEmptyElement(elementname);
                              Set<Entry<String, String>> meSet = elementAttribs.entrySet();
                              for( Entry<String, String> me : meSet ){
                                   writer.writeAttribute(me.getKey(), me.getValue());
                              }//end for me
                              elementAttribs.clear();
                              if( dbRefFound ){
                                   dbRefFound = false;
                              }
                              elementname = null;
                              break;
                         }
                         writer.writeEndElement();
                         elementname = null;
                         elementAttribs.clear();
                         break;
                    case XMLStreamConstants.CHARACTERS:
                         if( elementname != null  &&  
                              (lastEventType == XMLStreamConstants.START_ELEMENT || 
                               lastEventType == XMLStreamConstants.END_ELEMENT) ){
                              writer.writeStartElement(elementname);
                              Set<Entry<String, String>> meSet = elementAttribs.entrySet();
                              for( Entry<String, String> me : meSet ){
                                   writer.writeAttribute(me.getKey(), me.getValue());
                              }//end for me
                              elementAttribs.clear();
                              elementname = null;
                         }
          
                         if( !emptyDbRefFound ) {
                              writer.writeCharacters(reader.getText());
                         } else {
                              emptyDbRefFound = false;
                         }
                         break;
                    case XMLStreamConstants.COMMENT:
                         writer.writeComment(reader.getText());
                         break;
                    case XMLStreamConstants.CDATA:
                         writer.writeCData(reader.getText());
                         break;
                    case XMLStreamConstants.START_DOCUMENT:
                         writer.writeStartDocument("UTF-8", "1.0");
                         break;
                    case XMLStreamConstants.END_DOCUMENT:
                         writer.writeEndDocument();
                         break;
                    case XMLStreamConstants.ATTRIBUTE:
                    case XMLStreamConstants.NAMESPACE:
                         break;
                    default:
                         break;
                    }//end switch
                    lastEventType = event;
                    event = reader.next();
               }//end while
          
               System.out.println(out);
          }//end removeEmptyDbReference