Example usage for javax.xml.stream.events XMLEvent asStartElement

List of usage examples for javax.xml.stream.events XMLEvent asStartElement

Introduction

In this page you can find the example usage for javax.xml.stream.events XMLEvent asStartElement.

Prototype

public StartElement asStartElement();

Source Link

Document

Returns this event as a start element event, may result in a class cast exception if this event is not a start element.

Usage

From source file:org.openhab.binding.dwdunwetter.internal.data.DwdWarningsData.java

/**
 * Refreshes the Warnings Data//from w  ww  .ja  va  2 s  .c om
 */
public boolean refresh() {
    String rawData = dataAccessCached.getValue();
    if (StringUtils.isEmpty(rawData)) {
        logger.debug("No Data from Endpoint");
        return false;
    }

    cityData.clear();

    try {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(rawData));
        XMLEventReader eventReader = inputFactory.createXMLEventReader(reader);
        DwdWarningData gemeindeData = new DwdWarningData();
        boolean insideGemeinde = false;
        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();
            if (!insideGemeinde && event.isStartElement()) {
                DwdXmlTag xmlTag = DwdXmlTag.getDwdXmlTag(event.asStartElement().getName().getLocalPart());
                switch (xmlTag) {
                case WARNUNGEN_GEMEINDEN:
                    gemeindeData = new DwdWarningData();
                    insideGemeinde = true;
                    break;
                default:
                    break;
                }
            } else if (insideGemeinde && event.isStartElement()) {
                DwdXmlTag xmlTag = DwdXmlTag.getDwdXmlTag(event.asStartElement().getName().getLocalPart());
                switch (xmlTag) {
                case SEVERITY:
                    gemeindeData.setSeverity(Severity.getSeverity(getValue(eventReader)));
                    break;
                case DESCRIPTION:
                    gemeindeData.setDescription(getValue(eventReader));
                    break;
                case EFFECTIVE:
                    gemeindeData.setEffective(getTimestampValue(eventReader));
                    break;
                case EXPIRES:
                    gemeindeData.setExpires(getTimestampValue(eventReader));
                    break;
                case EVENT:
                    gemeindeData.setEvent(getValue(eventReader));
                    break;
                case STATUS:
                    gemeindeData.setStatus(getValue(eventReader));
                    break;
                case MSGTYPE:
                    gemeindeData.setMsgType(getValue(eventReader));
                    break;
                case HEADLINE:
                    gemeindeData.setHeadline(getValue(eventReader));
                    break;
                case ONSET:
                    gemeindeData.setOnset(getTimestampValue(eventReader));
                    break;
                case ALTITUDE:
                    gemeindeData.setAltitude(getBigDecimalValue(eventReader));
                    break;
                case CEILING:
                    gemeindeData.setCeiling(getBigDecimalValue(eventReader));
                    break;
                case IDENTIFIER:
                    gemeindeData.setId(getValue(eventReader));
                    break;
                case INSTRUCTION:
                    gemeindeData.setInstruction(getValue(eventReader));
                    break;
                case URGENCY:
                    gemeindeData.setUrgency(Urgency.getUrgency(getValue(eventReader)));
                    break;
                default:
                    break;
                }
            } else if (insideGemeinde && event.isEndElement()) {
                DwdXmlTag xmlTag = DwdXmlTag.getDwdXmlTag(event.asEndElement().getName().getLocalPart());
                switch (xmlTag) {
                case WARNUNGEN_GEMEINDEN:
                    if (!gemeindeData.isTest() && !gemeindeData.isCancel()) {
                        cityData.add(gemeindeData);
                    }
                    insideGemeinde = false;
                    break;
                default:
                    break;
                }
            }
        }
    } catch (XMLStreamException e) {
        logger.debug("Exception while parsing the XML Response", e);
        return false;
    }
    Collections.sort(cityData, new SeverityComparator());
    return true;
}

From source file:org.openhim.mediator.denormalization.EnrichRegistryStoredQueryActor.java

private String enrichStoredQueryXML(Identifier id, InputStream xml) throws XMLStreamException {
    XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(xml);
    StringWriter output = new StringWriter();
    XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(output);
    XMLEventFactory eventFactory = XMLEventFactory.newFactory();

    String curSlot = null;/*from  w  w w. j a va2s  .c  o m*/
    boolean patientIdSlot = false;

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

        if (event.getEventType() == XMLEvent.START_ELEMENT) {
            StartElement elem = event.asStartElement();
            if ("Slot".equals(elem.getName().getLocalPart())) {
                curSlot = elem.getAttributeByName(new QName("name")).getValue();
            } else if ("Value".equals(elem.getName().getLocalPart())
                    && ParseRegistryStoredQueryActor.PATIENT_ID_SLOT_TYPE.equals(curSlot)) {
                patientIdSlot = true;
                writer.add(event);
            }
        } else if (event.getEventType() == XMLEvent.END_ELEMENT) {
            EndElement elem = event.asEndElement();
            if (patientIdSlot && "Value".equals(elem.getName().getLocalPart())) {
                XMLEvent ecidEvent = eventFactory.createCharacters("'" + id.toString() + "'");
                writer.add(ecidEvent);
                patientIdSlot = false;
            }
        }

        if (!patientIdSlot) {
            writer.add(event);
        }
    }

    writer.close();
    return output.toString();
}

From source file:org.pentaho.di.trans.steps.xmlinputstream.XMLInputStream.java

private Object[] processEvent() throws KettleException {

    Object[] outputRowData = RowDataUtil.allocateRowData(data.outputRowMeta.size());
    XMLEvent e = null;
    try {//from ww  w.j a v  a2  s .c  o  m
        e = data.xmlEventReader.nextEvent();
    } catch (XMLStreamException ex) {
        throw new KettleException(ex);
    }

    int eventType = e.getEventType();
    if (data.pos_xml_data_type_numeric != -1) {
        outputRowData[data.pos_xml_data_type_numeric] = new Long(eventType);
    }
    if (data.pos_xml_data_type_description != -1) {
        if (eventType == 0 || eventType > eventDescription.length) {
            // unknown eventType
            outputRowData[data.pos_xml_data_type_description] = eventDescription[0] + "(" + eventType + ")";
        } else {
            outputRowData[data.pos_xml_data_type_description] = eventDescription[eventType];
        }
    }
    if (data.pos_xml_location_line != -1) {
        outputRowData[data.pos_xml_location_line] = new Long(e.getLocation().getLineNumber());
    }
    if (data.pos_xml_location_column != -1) {
        outputRowData[data.pos_xml_location_column] = new Long(e.getLocation().getColumnNumber());
    }

    switch (eventType) {

    case XMLStreamConstants.START_ELEMENT:
        data.elementLevel++;
        if (data.elementLevel > PARENT_ID_ALLOCATE_SIZE - 1) {
            throw new KettleException(BaseMessages.getString(PKG, "XMLInputStream.Log.TooManyNestedElements",
                    PARENT_ID_ALLOCATE_SIZE));
        }
        if (data.elementParentID[data.elementLevel] == null) {
            data.elementParentID[data.elementLevel] = data.elementID;
        }
        data.elementID++;
        data.elementLevelID[data.elementLevel] = data.elementID;

        String xml_data_name;
        if (meta.isEnableNamespaces()) {
            String prefix = e.asStartElement().getName().getPrefix();
            if (Utils.isEmpty(prefix)) {
                xml_data_name = e.asStartElement().getName().getLocalPart();
            } else { // add namespace prefix:
                xml_data_name = prefix + ":" + e.asStartElement().getName().getLocalPart();
            }
        } else {
            xml_data_name = e.asStartElement().getName().getLocalPart();
        }
        if (data.pos_xml_data_name >= 0) {
            outputRowData[data.pos_xml_data_name] = xml_data_name;
        }
        // store the name
        data.elementName[data.elementLevel] = xml_data_name;
        // store simple path
        data.elementPath[data.elementLevel] = data.elementPath[data.elementLevel - 1] + "/" + xml_data_name;

        // write Namespaces out
        if (meta.isEnableNamespaces()) {
            outputRowData = parseNamespaces(outputRowData, e);
        }

        // write Attributes out
        outputRowData = parseAttributes(outputRowData, e);

        break;

    case XMLStreamConstants.END_ELEMENT:
        parseEndElement(outputRowData, e.asEndElement());
        putRowOut(outputRowData);
        data.elementParentID[data.elementLevel + 1] = null;
        data.elementLevel--;
        outputRowData = null; // continue
        break;

    case XMLStreamConstants.SPACE:
        outputRowData = null; // ignore & continue
        break;

    case XMLStreamConstants.CHARACTERS:
    case XMLStreamConstants.CDATA:
        if (data.pos_xml_data_name >= 0) {
            outputRowData[data.pos_xml_data_name] = data.elementName[data.elementLevel];
        }
        String xml_data_value = e.asCharacters().getData();
        if (data.pos_xml_data_value >= 0) {
            if (meta.isEnableTrim()) {
                // optional trim is also eliminating white spaces, tab, cr, lf
                xml_data_value = Const.trim(xml_data_value);
            }
            outputRowData[data.pos_xml_data_value] = xml_data_value;
        }

        if (data.pos_xml_data_value < 0 || Utils.isEmpty((String) outputRowData[data.pos_xml_data_value])) {
            outputRowData = null; // ignore & continue
        }
        break;

    case XMLStreamConstants.PROCESSING_INSTRUCTION:
        outputRowData = null; // ignore & continue
        // TODO test if possible
        break;

    case XMLStreamConstants.COMMENT:
        outputRowData = null; // ignore & continue
        // TODO test if possible
        break;

    case XMLStreamConstants.ENTITY_REFERENCE:
        // should be resolved by default
        outputRowData = null; // ignore & continue
        break;

    case XMLStreamConstants.START_DOCUMENT:
        // just get this information out
        break;

    case XMLStreamConstants.END_DOCUMENT:
        // just get this information out
        break;

    default:
        logBasic("Event:" + eventType);
        outputRowData = null; // ignore & continue
    }

    return outputRowData;
}

From source file:org.pentaho.di.trans.steps.xmlinputstream.XMLInputStream.java

@SuppressWarnings("unchecked")
private Object[] parseNamespaces(Object[] outputRowData, XMLEvent e)
        throws KettleValueException, KettleStepException {
    Iterator<Namespace> iter = e.asStartElement().getNamespaces();
    if (iter.hasNext()) {
        Object[] outputRowDataNamespace = data.outputRowMeta.cloneRow(outputRowData);
        putRowOut(outputRowDataNamespace); // first put the element name info out
        // change data_type to ATTRIBUTE
        if (data.pos_xml_data_type_numeric != -1) {
            outputRowData[data.pos_xml_data_type_numeric] = new Long(XMLStreamConstants.NAMESPACE);
        }/* w  ww. j  a v  a 2s  .c om*/
        if (data.pos_xml_data_type_description != -1) {
            outputRowData[data.pos_xml_data_type_description] = eventDescription[XMLStreamConstants.NAMESPACE];
        }
    }
    while (iter.hasNext()) {
        Object[] outputRowDataNamespace = data.outputRowMeta.cloneRow(outputRowData);
        Namespace n = iter.next();
        outputRowDataNamespace[data.pos_xml_data_name] = n.getPrefix();
        outputRowDataNamespace[data.pos_xml_data_value] = n.getNamespaceURI();
        if (iter.hasNext()) {
            // send out the Namespace row
            putRowOut(outputRowDataNamespace);
        } else {
            // last row: this will be sent out by the outer loop
            outputRowData = outputRowDataNamespace;
        }
    }

    return outputRowData;
}

From source file:org.pentaho.di.trans.steps.xmlinputstream.XMLInputStream.java

@SuppressWarnings("unchecked")
private Object[] parseAttributes(Object[] outputRowData, XMLEvent e)
        throws KettleValueException, KettleStepException {
    Iterator<Attribute> iter = e.asStartElement().getAttributes();
    if (iter.hasNext()) {
        Object[] outputRowDataAttribute = data.outputRowMeta.cloneRow(outputRowData);
        putRowOut(outputRowDataAttribute); // first put the element name (or namespace) info out
        // change data_type to ATTRIBUTE
        if (data.pos_xml_data_type_numeric != -1) {
            outputRowData[data.pos_xml_data_type_numeric] = new Long(XMLStreamConstants.ATTRIBUTE);
        }/*w w  w .ja  v  a2 s . c o m*/
        if (data.pos_xml_data_type_description != -1) {
            outputRowData[data.pos_xml_data_type_description] = eventDescription[XMLStreamConstants.ATTRIBUTE];
        }
    }
    while (iter.hasNext()) {
        Object[] outputRowDataAttribute = data.outputRowMeta.cloneRow(outputRowData);
        Attribute a = iter.next();
        parseAttribute(outputRowDataAttribute, a, meta.isEnableNamespaces());
        if (iter.hasNext()) {
            // send out the Attribute row
            putRowOut(outputRowDataAttribute);
        } else {
            // last row: this will be sent out by the outer loop
            outputRowData = outputRowDataAttribute;
        }
    }

    return outputRowData;
}

From source file:org.plasma.sdo.xml.StreamUnmarshaller.java

private StreamObject read(XMLStreamReader streamReader) throws XMLStreamException, UnmarshallerException {
    int eventType;
    StreamObject root = null;//from  www  .  ja  v  a2s.  c o  m

    while (streamReader.hasNext()) {
        eventType = streamReader.next();
        XMLEvent event = allocateXMLEvent(streamReader);
        switch (eventType) {
        case XMLEvent.START_ELEMENT:
            QName name = event.asStartElement().getName();
            String uri = name.getNamespaceURI();
            if (uri != null && uri.trim().length() > 0)
                this.currentNamespaceUri = uri.trim();
            if (stack.size() == 0) {
                String typeName = name.getLocalPart();
                PlasmaType type = (PlasmaType) PlasmaTypeHelper.INSTANCE.getType(currentNamespaceUri, typeName);
                if (log.isDebugEnabled())
                    log.debug("unmarshaling root: " + type.getURI() + "#" + type.getName());
                root = new StreamObject(type, name, event.getLocation());
                stack.push(root);
            } else {
                StreamObject sreamObject = (StreamObject) stack.peek();
                PlasmaType type = sreamObject.getType();
                QName elemName = event.asStartElement().getName();
                PlasmaProperty property = getPropertyByLocalName(event, type, elemName.getLocalPart());
                if (property.getType().isDataType()) {
                    // still need characters event to populate this property. We expect to
                    // pop this back off the stack after its characters event is processed below
                    stack.push(new StreamProperty((PlasmaType) property.getType(), property, name,
                            event.getLocation()));
                    break; // we expect no attributes !!
                } else {
                    if (log.isDebugEnabled())
                        log.debug("unmarshaling: " + property.getType().getURI() + "#"
                                + property.getType().getName());
                    // The source is a reference property but we don't know at this point
                    // whether its a reference object.

                    // Push the new DO so we can value its contents on subsequent events
                    stack.push(new StreamObject((PlasmaType) property.getType(), property, name,
                            event.getLocation()));
                }
            }
            StreamObject streamObject = (StreamObject) stack.peek();
            readAttributes(event, streamObject);
            break;
        case XMLEvent.END_ELEMENT:
            StreamNode node = stack.pop();
            if (stack.size() == 0)
                break;

            // link stream objects creating an initial graph
            StreamObject other = (StreamObject) stack.peek();
            if (node instanceof StreamProperty) {
                StreamProperty streamProp = (StreamProperty) node;
                if (this.charbuf.length() > 0) {
                    readCharacters(streamProp, this.charbuf.toString(), event);
                    this.charbuf.setLength(0);
                }
                link((StreamProperty) node, other);
            } else {
                link((StreamObject) node, other);
            }
            break;
        case XMLEvent.CHARACTERS:
            if (stack.size() == 0)
                break;
            String data = event.asCharacters().getData();
            if (log.isDebugEnabled())
                log.debug("unmarshaling characters: " + String.valueOf(data));
            if (data == null) {
                break; // ignore null
            }
            if (data.contains(">")) {
                //Note: we even get escaped '>' char here so 
                // can't accurately determine well-formedness 
                Location loc = event.getLocation();
                String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
                msg += " - document may not be well-formed";
                log.warn(msg);
            }
            StreamNode streamNode = stack.peek();
            if (streamNode instanceof StreamProperty) {
                this.charbuf.append(data);
            } else {
                if (log.isDebugEnabled()) {
                    StreamObject streamObj = (StreamObject) streamNode;
                    Location loc = event.getLocation();
                    String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
                    msg += " - ignoring character(s) data '" + data + "' for complex type "
                            + streamObj.getType().getURI() + "#" + streamObj.getType().getName();
                    log.debug(msg);
                }
            }
            break;
        default:
            logEventInfo(event);
        }
    }
    return root;
}

From source file:org.plasma.sdo.xml.StreamUnmarshaller.java

@SuppressWarnings("unchecked")
private void readAttributes(XMLEvent event, StreamObject prototype) throws UnmarshallerException {
    boolean serialIdAttributeFound = false;
    PlasmaType type = prototype.getType();
    Iterator<Attribute> iter = event.asStartElement().getAttributes();
    while (iter.hasNext()) {
        Attribute attrib = (Attribute) iter.next();
        QName attribName = attrib.getName();
        String localPart = attribName.getLocalPart();
        if (XMLConstants.ATTRIB_TARGET_NAMESPACE.equals(localPart)) {
            continue;
        } else if (XMLConstants.XMLSCHEMA_INSTANCE_NAMESPACE_URI.equals(attribName.getNamespaceURI())) {
            // its an XSI attribute we care about
            if ("type".equals(localPart)) {
                String xsiTypeLocalName = attrib.getValue();
                int delim = xsiTypeLocalName.indexOf(":");
                if (delim >= 0)
                    xsiTypeLocalName = xsiTypeLocalName.substring(delim + 1);
                // In order to validate XML graphs with both containment
                // and non containment references with an XML schema,
                // the Schema types must be generated with XSI 'xsi:type'
                // attribute to indicate a subclass. The subclass name will be
                // either 1.) matching the local for the type, wherein we
                // assume a containment reference or 2.) matching a generated
                // synthetic name for the non-containment reference for the
                // type, e.g. 'MyTypeRef'. So for containment references
                // we should find 'xsi:type="prefix:MyType" and for 
                // non-containment references we should find 'xsi:type="prefix:MyTypeRef"
                // or some other generated suffix with no name collisions. 
                if (!xsiTypeLocalName.equals(type.getLocalName())) {
                    if (log.isDebugEnabled())
                        log.debug("type as non-containment reference, " + type.getURI() + "#" + type.getName());
                    prototype.setNonContainmentReference(true);
                }/*from  ww  w. j a va  2 s. c  om*/
            }
            continue;
        }

        PlasmaProperty property = findPropertyByLocalName(type, localPart);
        if (property == null) {
            if (!SchemaUtil.getSerializationAttributeName().equals(localPart)) {
                Location loc = event.getLocation();
                String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
                msg += " - no property '" + localPart + "' found defined for type " + type.getURI() + "#"
                        + type.getName();
                throw new UnmarshallerException(msg);
            } else {
                prototype.setSerialId(attrib.getValue());
                serialIdAttributeFound = true;
                continue;
            }
        }

        if (property.getType().isDataType()) {
            if (property.isMany()) {
                Location loc = event.getLocation();
                String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
                msg += " - unexpected 'many' propery (" + type.getURI() + "#" + type.getName() + "."
                        + property.getName() + ") can only set singular properties from attribute '" + localPart
                        + "'";
                throw new UnmarshallerException(msg);
            }
            Object value = PlasmaDataHelper.INSTANCE.convert(property, attrib.getValue());
            if (!property.isReadOnly()) {
                prototype.set(property, value);
            } else {
                DataFlavor dataFlavor = property.getDataFlavor();
                switch (dataFlavor) {
                case integral:
                    Location loc = event.getLocation();
                    String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
                    msg += " - cannot set integral readonly propery (" + property.getName()
                            + ") - ignoring attribute data '" + attrib.getValue() + "' for readonly propery, "
                            + type.getURI() + "#" + type.getName() + "." + property.getName();
                    log.warn(msg);
                    break;
                default:
                    prototype.set(property, value);
                }
            }
        } else {
            Location loc = event.getLocation();
            String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
            msg += " - expected datatype property - attribute '" + localPart
                    + "' is a reference property as defined in type " + type.getURI() + "#" + type.getName();
            throw new UnmarshallerException(msg);
        }
    }

    if (!serialIdAttributeFound) {
        Location loc = event.getLocation();
        String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
        msg += " - expected serialization attribute '" + SchemaUtil.getSerializationAttributeName()
                + "' for type " + type.getURI() + "#" + type.getName();
        throw new UnmarshallerException(msg);
    }
}

From source file:org.qi4j.valueserialization.stax.StaxValueDeserializer.java

@Override
protected Object readPlainValue(XMLEventReader input) throws Exception {
    if (!input.hasNext()) {
        return null;
    }/*from w w w  .j  av  a 2s .  com*/
    XMLEvent nextEvent = input.nextEvent();
    if (nextEvent.getEventType() == XMLEvent.START_ELEMENT
            && "null".equals(nextEvent.asStartElement().getName().getLocalPart())) {
        input.nextTag();
        return null;
    }
    if (nextEvent.getEventType() != XMLEvent.CHARACTERS) {
        throw new ValueSerializationException("Expected characters but got: " + nextEvent);
    }
    String stringValue = nextEvent.asCharacters().getData();
    return detectAndConvertStringValue(stringValue);
}

From source file:org.qi4j.valueserialization.stax.StaxValueDeserializer.java

@Override
protected <T> Collection<T> readArrayInCollection(XMLEventReader input,
        Function<XMLEventReader, T> deserializer, Collection<T> collection) throws Exception {
    if (!input.hasNext()) {
        return null;
    }/*  www.ja  va  2s .c  om*/
    XMLEvent nextTag = input.nextTag();
    if (nextTag.isStartElement() && "null".equals(nextTag.asStartElement().getName().getLocalPart())) {
        input.nextTag();
        return null;
    }
    if (!nextTag.isStartElement() || !"array".equals(nextTag.asStartElement().getName().getLocalPart())) {
        throw new ValueSerializationException("Expected an <array/> but got: " + nextTag);
    }
    WHILE: while (input.hasNext()) {
        XMLEvent currentTag = input.nextTag();
        if (currentTag.isEndElement()) {
            String endElementName = currentTag.asEndElement().getName().getLocalPart();
            switch (endElementName) {
            case "array":
                break WHILE;
            case "value":
                continue;
            }
        }
        if (!"value".equals(currentTag.asStartElement().getName().getLocalPart())) {
            throw new ValueSerializationException("Expected a <value/> but got: " + currentTag);
        }
        T item = deserializer.map(input);
        collection.add(item);
    }
    return collection;
}

From source file:org.qi4j.valueserialization.stax.StaxValueDeserializer.java

@Override
protected <K, V> Map<K, V> readMapInMap(XMLEventReader input, Function<XMLEventReader, K> keyDeserializer,
        Function<XMLEventReader, V> valueDeserializer, Map<K, V> map) throws Exception {
    if (!input.hasNext()) {
        return null;
    }/*  www .  ja v a2s .c o  m*/
    XMLEvent nextTag = input.nextTag();
    if (nextTag.isStartElement() && "null".equals(nextTag.asStartElement().getName().getLocalPart())) {
        input.nextTag();
        return null;
    }
    if (!nextTag.isStartElement() || !"array".equals(nextTag.asStartElement().getName().getLocalPart())) {
        throw new ValueSerializationException("Expected an <array/> but got: " + nextTag);
    }
    XMLEvent currentTag = input.nextTag(); // <object>
    while (!currentTag.isEndElement() || !"array".equals(currentTag.asEndElement().getName().getLocalPart())) {
        if (!currentTag.isStartElement()
                || !"object".equals(currentTag.asStartElement().getName().getLocalPart())) {
            throw new ValueSerializationException("Expected an <object/> but got: " + nextTag);
        }
        currentTag = input.nextTag(); // <field>
        K key = null;
        V value = null;
        while (!currentTag.isEndElement()
                || !"object".equals(currentTag.asEndElement().getName().getLocalPart())) {
            input.nextTag(); // <name>
            String keyOrValue = input.nextEvent().asCharacters().getData();
            input.nextTag(); // </name>
            input.nextTag(); // <value>
            switch (keyOrValue) {
            case "key":
                key = keyDeserializer.map(input);
                break;
            case "value":
                value = valueDeserializer.map(input);
                break;
            default:
                readObjectTree(input);
                break;
            }
            input.nextTag(); // </value>
            input.nextTag(); // </field>
            currentTag = input.nextTag();
        }
        if (key != null) {
            map.put(key, value);
        }
        currentTag = input.nextTag();
    }
    return map;
}