Java Code Examples for javax.xml.stream.events.XMLEvent#isCharacters()

The following examples show how to use javax.xml.stream.events.XMLEvent#isCharacters() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: StAXAntPathIterator.java    From secure-data-service with Apache License 2.0 6 votes vote down vote up
protected void iterateContent(ContentIterator contentIterator) throws XMLStreamException {
    Stack<StartElement> parents = new Stack<StartElement>();

    do {
        XMLEvent xmlEvent = reader.nextEvent();

        if (xmlEvent.isStartElement()) {
            parents.add(xmlEvent.asStartElement());
        } else if (xmlEvent.isEndElement()) {
            parents.pop();
        }

        if (!(xmlEvent.isCharacters() && xmlEvent.asCharacters().isWhiteSpace())) {
            contentIterator.visit(xmlEvent);
        }
    } while (parents.size() > 0 && reader.hasNext());

    contentIterator.visit(NEW_LINE_EVENT);
}
 
Example 2
Source File: StAXFilteredEvent.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 6 votes vote down vote up
public String getElementText() throws XMLStreamException
{
    StringBuffer buffer = new StringBuffer();
    XMLEvent e = nextEvent();
    if (!e.isStartElement())
        throw new XMLStreamException(
        CommonResourceBundle.getInstance().getString("message.mustBeOnSTART_ELEMENT"));

    while(hasNext()) {
        e = nextEvent();
        if(e.isStartElement())
            throw new XMLStreamException(
            CommonResourceBundle.getInstance().getString("message.getElementTextExpectTextOnly"));
        if(e.isCharacters())
            buffer.append(((Characters) e).getData());
        if(e.isEndElement())
            return buffer.toString();
    }
    throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.END_ELEMENTnotFound"));
}
 
Example 3
Source File: AtomDeserializer.java    From olingo-odata4 with Apache License 2.0 6 votes vote down vote up
private void count(final XMLEventReader reader, final StartElement start, final EntityCollection entitySet)
    throws XMLStreamException {

  boolean foundEndElement = false;
  while (reader.hasNext() && !foundEndElement) {
    final XMLEvent event = reader.nextEvent();

    if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
      entitySet.setCount(Integer.valueOf(event.asCharacters().getData()));
    }

    if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
      foundEndElement = true;
    }
  }
}
 
Example 4
Source File: ParseWikipedia.java    From WikipediaEntities with GNU Affero General Public License v3.0 6 votes vote down vote up
private String parseTextContents(XMLEventReader eventReader) throws XMLStreamException {
  // Chances are that we'll only need one string.
  String ret = null;
  buf.setLength(0);
  while(eventReader.hasNext()) {
    XMLEvent event = eventReader.nextEvent();
    if(event.isEndElement())
      break;
    if(event.isCharacters()) {
      if(ret == null)
        ret = event.asCharacters().getData();
      else { // Need to use the buffer
        if(buf.length() == 0)
          buf.append(ret);
        buf.append(event.asCharacters().getData());
      }
    }
  }
  if(buf.length() > 0) {
    ret = buf.toString();
  }
  return ret;
}
 
Example 5
Source File: StAXFilteredEvent.java    From jdk8u60 with GNU General Public License v2.0 6 votes vote down vote up
public String getElementText() throws XMLStreamException
{
    StringBuffer buffer = new StringBuffer();
    XMLEvent e = nextEvent();
    if (!e.isStartElement())
        throw new XMLStreamException(
        CommonResourceBundle.getInstance().getString("message.mustBeOnSTART_ELEMENT"));

    while(hasNext()) {
        e = nextEvent();
        if(e.isStartElement())
            throw new XMLStreamException(
            CommonResourceBundle.getInstance().getString("message.getElementTextExpectTextOnly"));
        if(e.isCharacters())
            buffer.append(((Characters) e).getData());
        if(e.isEndElement())
            return buffer.toString();
    }
    throw new XMLStreamException(CommonResourceBundle.getInstance().getString("message.END_ELEMENTnotFound"));
}
 
Example 6
Source File: XMLEventReaderImpl.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
/** Skips any insignificant space events until a START_ELEMENT or
 * END_ELEMENT is reached. If anything other than space characters are
 * encountered, an exception is thrown. This method should
 * be used when processing element-only content because
 * the parser is not able to recognize ignorable whitespace if
 * the DTD is missing or not interpreted.
 * @throws XMLStreamException if anything other than space characters are encountered
 */
public XMLEvent nextTag() throws XMLStreamException {
    //its really a pain if there is peeked event before calling nextTag()
    if(fPeekedEvent != null){
        //check the peeked event first.
        XMLEvent event = fPeekedEvent;
        fPeekedEvent = null ;
        int eventType = event.getEventType();
        //if peeked event is whitespace move to the next event
        //if peeked event is PI or COMMENT move to the next event
        if( (event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT
        || eventType == XMLStreamConstants.START_DOCUMENT){
            event = nextEvent();
            eventType = event.getEventType();
        }

        //we have to have the while loop because there can be many PI or comment event in sucession
        while((event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT){

            event = nextEvent();
            eventType = event.getEventType();
        }

        if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
            throw new XMLStreamException("expected start or end tag", event.getLocation());
        }
        return event;
    }

    //if there is no peeked event -- delegate the work of getting next event to fXMLReader
    fXMLReader.nextTag();
    return (fLastEvent = fXMLEventAllocator.allocate(fXMLReader));
}
 
Example 7
Source File: WindowSuffixTransformer.java    From recheck with GNU Affero General Public License v3.0 5 votes vote down vote up
protected boolean updatePath( final XMLEvent event, final XMLEventWriter eventWriter ) throws XMLStreamException {
	if ( isInPath && event.isCharacters() ) {
		final Characters characters = event.asCharacters();
		final String window = characters.getData();

		isWindowPath = "Window".equals( window );

		final String replace = window.replaceFirst( "Window", "Window_0" );
		eventWriter.add( characters( replace ) );
		return true;
	}
	return false;
}
 
Example 8
Source File: PathAndType2LowerCaseTransformer.java    From recheck with GNU Affero General Public License v3.0 5 votes vote down vote up
@Override
public void convert( final XMLEvent event, final XMLEventWriter eventWriter ) throws XMLStreamException {
	// <attribute xsi:type="pathAttribute" key="path">Window/JRootPane_0/JPane_1</attribute>
	if ( isStartElementNamed( event, tagname ) && hasAttribute( event, "key", "path" ) ) {
		isInPath = true;
	}

	if ( isInPath && event.isCharacters() ) {
		path += event.asCharacters().getData().trim();
		return;
	}

	if ( isInPath && isEndElementNamed( event, tagname ) ) {
		eventWriter.add( characters( path.toLowerCase() ) );
		isInPath = false;
		path = "";
	}

	if ( isStartElementNamed( event, tagname ) && hasAttribute( event, "key", "type" ) ) {
		isInType = true;
	}

	if ( isInType && event.isCharacters() ) {
		type += event.asCharacters().getData().trim();
		return;
	}

	if ( isInType && isEndElementNamed( event, tagname ) ) {
		eventWriter.add( characters( type.toLowerCase() ) );
		isInType = false;
		type = "";
	}

	eventWriter.add( event );
}
 
Example 9
Source File: Path2XPathTransformer.java    From recheck with GNU Affero General Public License v3.0 5 votes vote down vote up
@Override
public void convert( final XMLEvent event, final XMLEventWriter eventWriter ) throws XMLStreamException {
	// <attribute xsi:type="pathAttribute" key="path">Window/JRootPane_0/JPane_1</attribute>
	if ( isStartElementNamed( event, tagname ) && hasAttribute( event, "key", "path" ) ) {
		isInPath = true;
	}

	if ( isInPath && event.isCharacters() ) {
		path += event.asCharacters().getData().trim();
		return;
	}

	if ( isInPath && isEndElementNamed( event, tagname ) ) {
		eventWriter.add( characters( toXPath( path ) ) );
		isInPath = false;
		path = "";
	}

	// <attribute xsi:type="suffixAttribute" key="suffix">1</attribute>
	if ( isStartElementNamed( event, tagname ) && hasAttribute( event, "key", "suffix" ) ) {
		isInSuffix = true;
	}

	if ( isInSuffix && event.isCharacters() ) {
		suffix += event.asCharacters().getData().trim();
		return;
	}

	if ( isEndElementNamed( event, tagname ) ) {
		try {
			eventWriter.add( characters( valueOf( parseInt( suffix ) + 1 ) ) );
		} catch ( final NumberFormatException exc ) {
			eventWriter.add( characters( suffix ) );
		}
		isInSuffix = false;
		suffix = "";
	}

	eventWriter.add( event );
}
 
Example 10
Source File: AtomGeoValueDeserializer.java    From olingo-odata4 with Apache License 2.0 5 votes vote down vote up
private List<Point> points(final XMLEventReader reader, final StartElement start,
    final EdmPrimitiveTypeKind type, final SRID srid) throws XMLStreamException {

  final List<Point> result = new ArrayList<>();

  boolean foundEndProperty = false;
  while (reader.hasNext() && !foundEndProperty) {
    final XMLEvent event = reader.nextEvent();

    if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
      final String[] pointInfo = event.asCharacters().getData().split(" ");

      final Point point = new Point(GeoUtils.getDimension(type), srid);
      try {
        point.setX(EdmDouble.getInstance().valueOfString(pointInfo[0], null, null,
            Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
        point.setY(EdmDouble.getInstance().valueOfString(pointInfo[1], null, null,
            Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null, Double.class));
      } catch (EdmPrimitiveTypeException e) {
        throw new XMLStreamException("While deserializing point coordinates as double", e);
      }
      result.add(point);
    }

    if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
      foundEndProperty = true;
    }
  }

  // handles bad input, e.g. things like <gml:pos/>
  if (result.isEmpty()) {
    result.add(new Point(GeoUtils.getDimension(type), srid));
  }

  return result;
}
 
Example 11
Source File: XMLEventReaderImpl.java    From Bytecoder with Apache License 2.0 5 votes vote down vote up
/** Skips any insignificant space events until a START_ELEMENT or
 * END_ELEMENT is reached. If anything other than space characters are
 * encountered, an exception is thrown. This method should
 * be used when processing element-only content because
 * the parser is not able to recognize ignorable whitespace if
 * the DTD is missing or not interpreted.
 * @throws XMLStreamException if anything other than space characters are encountered
 */
public XMLEvent nextTag() throws XMLStreamException {
    //its really a pain if there is peeked event before calling nextTag()
    if(fPeekedEvent != null){
        //check the peeked event first.
        XMLEvent event = fPeekedEvent;
        fPeekedEvent = null ;
        int eventType = event.getEventType();
        //if peeked event is whitespace move to the next event
        //if peeked event is PI or COMMENT move to the next event
        if( (event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT
        || eventType == XMLStreamConstants.START_DOCUMENT){
            event = nextEvent();
            eventType = event.getEventType();
        }

        //we have to have the while loop because there can be many PI or comment event in sucession
        while((event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT){

            event = nextEvent();
            eventType = event.getEventType();
        }

        if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
            throw new XMLStreamException("expected start or end tag", event.getLocation());
        }
        return event;
    }

    //if there is no peeked event -- delegate the work of getting next event to fXMLReader
    fXMLReader.nextTag();
    return (fLastEvent = fXMLEventAllocator.allocate(fXMLReader));
}
 
Example 12
Source File: MetadataParser.java    From olingo-odata4 with Apache License 2.0 5 votes vote down vote up
private String elementValue(XMLEventReader reader, StartElement element) throws XMLStreamException {
  while (reader.hasNext()) {
    XMLEvent event = reader.peek();
    if (event.isStartElement() || event.isEndElement()) {
      return null;
    } else if (event.isCharacters()){
      reader.nextEvent();
      String data = event.asCharacters().getData();
      if (data.trim().length() > 0) {
        return data.trim();
      }
    }
  }    
  return null;
}
 
Example 13
Source File: XmlJavaxFormat.java    From jigsaw-payment with Apache License 2.0 5 votes vote down vote up
private void handleMissingField(String fieldName, XMLEventReader parser,
        XMLEvent event, ExtensionRegistry extensionRegistry, 
        UnknownFieldSet.Builder builder) throws XMLStreamException {
	
    // skip over the unknown fields, since we can't map them by id, then this message must not know about them.
    // We 'could' map them into the UnknownFieldSet, however none of the other formatters support this..
    // but in the future it would probably be useful for the case: Message A (v2) -> Message B (v1) -> Xml -> Message A (v2) 
    // this would require extra meta data in the xml to know the type of the unknown-field.
    
    
    if (event.isStartElement()) {
        /**
         * This loop will eat up everything inside "6"
         * So when this method is called, fieldName = 6, and event is set at index="11"
         * <unknown-field index="6">
         *      <unknown-field index="11">566667</unknown-field>
         *      <unknown-field index="15">
         *          <unknown-field index="16">566667</unknown-field>
         *      </unknown-field>
         * </unknown-field>
         */
        int depth = 1; // we start 1 level down, the value of "6"
        while (parser.hasNext()) {
            XMLEvent nextEvent = parser.nextEvent();
            if (nextEvent.isEndElement()) {
                depth--;
                if (depth <= 0 && parser.peek().isEndElement()) {
                    break;
                }
            } else if (nextEvent.isStartElement()) {
                depth++;
            }
        }
    } else if (event.isCharacters()) {
        // done, let it slide.
    }
}
 
Example 14
Source File: TestEventReader.java    From woodstox with Apache License 2.0 5 votes vote down vote up
public void testEventReaderLongSegments()
    throws XMLStreamException
{
    /* Ok. And here we should just check that we do not get 2 adjacent
     * separate Characters event. We can try to trigger this by long
     * segment and a set of char entities...
     */
    final String XML =
        "<root>Some text and &amp; also &quot;quoted&quot; stuff..."
        +" not sure If we\r\nreally need anything much more but"
        +" let's still make this longer"
        +"</root>";
    ;
	
    // Need to disable coalescing though for test to work:
    XMLEventReader er = getReader(XML, false);
    XMLEvent evt = er.nextEvent(); // start document
    assertTrue(evt.isStartDocument());
    assertTrue(er.nextEvent().isStartElement());
    assertTrue(er.nextEvent().isCharacters());

    evt = er.nextEvent();
    if (evt.isEndElement()) {
        ; // good
    } else {
        if (evt.isCharacters()) {
            fail("Even in the absence of coalescing, event reader should not split CHARACTERS segments (Woodstox guarantee): did get 2 adjacent separate Characters events.");
        } else { // hmmh. strange
            fail("Unexpected event object type after CHARACTERS: "+evt.getClass());
        }
    }
}
 
Example 15
Source File: ODataXmlDeserializer.java    From olingo-odata4 with Apache License 2.0 5 votes vote down vote up
private StartElement getStartElement(final XMLEventReader reader) throws XMLStreamException {
  while (reader.hasNext()) {
    final XMLEvent innerEvent = reader.peek();
    if (innerEvent.isCharacters() && innerEvent.asCharacters().isWhiteSpace()) {
      reader.nextEvent();
    } else if (innerEvent.isStartElement()) {
      return innerEvent.asStartElement();
    } else if (innerEvent.isEndElement() && inlineQName.equals(innerEvent.asEndElement().getName())) {
      return null;
    }
  }
  return null;
}
 
Example 16
Source File: ODataXmlDeserializer.java    From olingo-odata4 with Apache License 2.0 5 votes vote down vote up
private void count(final XMLEventReader reader, final StartElement start, final EntityCollection entitySet)
    throws XMLStreamException {

  boolean foundEndElement = false;
  while (reader.hasNext() && !foundEndElement) {
    final XMLEvent event = reader.nextEvent();
    if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
      entitySet.setCount(Integer.valueOf(event.asCharacters().getData()));
    }
    if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
      foundEndElement = true;
    }
  }
}
 
Example 17
Source File: XMLEventReaderImpl.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
/** Skips any insignificant space events until a START_ELEMENT or
 * END_ELEMENT is reached. If anything other than space characters are
 * encountered, an exception is thrown. This method should
 * be used when processing element-only content because
 * the parser is not able to recognize ignorable whitespace if
 * the DTD is missing or not interpreted.
 * @throws XMLStreamException if anything other than space characters are encountered
 */
public XMLEvent nextTag() throws XMLStreamException {
    //its really a pain if there is peeked event before calling nextTag()
    if(fPeekedEvent != null){
        //check the peeked event first.
        XMLEvent event = fPeekedEvent;
        fPeekedEvent = null ;
        int eventType = event.getEventType();
        //if peeked event is whitespace move to the next event
        //if peeked event is PI or COMMENT move to the next event
        if( (event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT
        || eventType == XMLStreamConstants.START_DOCUMENT){
            event = nextEvent();
            eventType = event.getEventType();
        }

        //we have to have the while loop because there can be many PI or comment event in sucession
        while((event.isCharacters() && event.asCharacters().isWhiteSpace())
        || eventType == XMLStreamConstants.PROCESSING_INSTRUCTION
        || eventType == XMLStreamConstants.COMMENT){

            event = nextEvent();
            eventType = event.getEventType();
        }

        if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
            throw new XMLStreamException("expected start or end tag", event.getLocation());
        }
        return event;
    }

    //if there is no peeked event -- delegate the work of getting next event to fXMLReader
    fXMLReader.nextTag();
    return (fLastEvent = fXMLEventAllocator.allocate(fXMLReader));
}
 
Example 18
Source File: XmlMerger.java    From aion-germany with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Read all {@link javax.xml.stream.events.XMLEvent}'s from specified file and write them onto the {@link javax.xml.stream.XMLEventWriter}
 *
 * @param file
 *            File to import
 * @param skipRoot
 *            Skip-root flag
 * @param writer
 *            Destenation writer
 * @throws XMLStreamException
 *             On event reading/writing error.
 * @throws FileNotFoundException
 *             if the reading file does not exist, is a directory rather than a regular file, or for some other reason cannot be opened for reading.
 */
private void importFile(File file, boolean skipRoot, XMLEventWriter writer, Properties metadata) throws XMLStreamException, IOException {
	logger.debug("Appending file " + file);
	metadata.setProperty(file.getPath(), makeHash(file));

	XMLEventReader reader = null;

	try {
		reader = inputFactory.createXMLEventReader(new FileReader(file));

		QName firstTagQName = null;

		while (reader.hasNext()) {
			XMLEvent event = reader.nextEvent();

			// skip start and end of document.
			if (event.isStartDocument() || event.isEndDocument()) {
				continue;
			}
			// skip all comments.
			if (event instanceof Comment) {
				continue;
			}
			// skip white-spaces and all ignoreable white-spaces.
			if (event.isCharacters()) {
				if (event.asCharacters().isWhiteSpace() || event.asCharacters().isIgnorableWhiteSpace()) {
					continue;
				}
			}

			// modify root-tag of imported file.
			if (firstTagQName == null && event.isStartElement()) {
				firstTagQName = event.asStartElement().getName();

				if (skipRoot) {
					continue;
				}
				else {
					StartElement old = event.asStartElement();

					event = eventFactory.createStartElement(old.getName(), old.getAttributes(), null);
				}
			}

			// if root was skipped - skip root end too.
			if (event.isEndElement() && skipRoot && event.asEndElement().getName().equals(firstTagQName)) {
				continue;
			}

			// finally - write tag
			writer.add(event);
		}
	}
	finally {
		if (reader != null) {
			try {
				reader.close();
			}
			catch (Exception ignored) {
			}
		}
	}
}
 
Example 19
Source File: AtomDeserializer.java    From olingo-odata4 with Apache License 2.0 4 votes vote down vote up
private Object fromComplexOrEnum(final XMLEventReader reader, final StartElement start)
    throws XMLStreamException, EdmPrimitiveTypeException {

  Object value = null;

  boolean foundEndProperty = false;
  while (reader.hasNext() && !foundEndProperty) {
    final XMLEvent event = reader.nextEvent();

    if (event.isStartElement()) {
      if (value == null) {
        value = new ComplexValue();
      }

      if (Constants.QNAME_ATOM_ELEM_LINK.equals(event.asStartElement().getName())) {
        final Link link = new Link();
        final Attribute rel = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_REL));
        if (rel != null) {
          link.setRel(rel.getValue());
        }
        final Attribute title = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TITLE));
        if (title != null) {
          link.setTitle(title.getValue());
        }
        final Attribute href = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_HREF));
        if (href != null) {
          link.setHref(href.getValue());
        }
        final Attribute type = event.asStartElement().getAttributeByName(QName.valueOf(Constants.ATTR_TYPE));
        if (type != null) {
          link.setType(type.getValue());
        }

        if (link.getRel().startsWith(Constants.NS_NAVIGATION_LINK_REL)) {

          ((ComplexValue) value).getNavigationLinks().add(link);
          inline(reader, event.asStartElement(), link);
        } else if (link.getRel().startsWith(Constants.NS_ASSOCIATION_LINK_REL)) {

          ((Valuable) value).asComplex().getAssociationLinks().add(link);
        }
      } else {
        ((ComplexValue) value).getValue().add(property(reader, event.asStartElement()));
      }
    }

    if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
      value = event.asCharacters().getData();
    }

    if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
      foundEndProperty = true;
    }
  }

  return value;
}
 
Example 20
Source File: XmlRecordSource.java    From nifi with Apache License 2.0 4 votes vote down vote up
private XmlNode readNext(final StartElement startElement) throws XMLStreamException, IOException {
    // Parse everything until we encounter the end element
    final StringBuilder content = new StringBuilder();
    final Map<String, XmlNode> childNodes = new LinkedHashMap<>();

    while (xmlEventReader.hasNext()) {
        final XMLEvent xmlEvent = xmlEventReader.nextEvent();

        if (xmlEvent.isEndDocument()) {
            throw new EOFException("Expected to encounter End-of-Element tag for start tag '" + startElement.getName() + "'");
        }

        if (xmlEvent.isEndElement()) {
            break;
        }

        if (xmlEvent.isCharacters()) {
            final Characters characters = xmlEvent.asCharacters();
            if (!characters.isWhiteSpace()) {
                content.append(characters.getData());
            }
        }

        if (xmlEvent.isStartElement()) {
            final StartElement childStartElement = xmlEvent.asStartElement();
            final XmlNode childNode = readNext(childStartElement);
            final String childName = childStartElement.getName().getLocalPart();

            final XmlNode existingNode = childNodes.get(childName);
            if (existingNode == null) {
                childNodes.put(childName, childNode);
            } else if (existingNode.getNodeType() == XmlNodeType.ARRAY) {
                ((XmlArrayNode) existingNode).addElement(childNode);
            } else {
                final XmlArrayNode arrayNode = new XmlArrayNode(childStartElement.getName().getLocalPart());
                arrayNode.addElement(existingNode);
                arrayNode.addElement(childNode);
                childNodes.put(childName, arrayNode);
            }
        }
    }

    final String nodeName = startElement.getName().getLocalPart();
    if (childNodes.isEmpty()) {
        return new XmlTextNode(nodeName, content.toString().trim());
    } else {
        return new XmlContainerNode(nodeName, childNodes);
    }
}