All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.n52.svalbard.decode.stream.xml.AbstractElementXmlStreamReader Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
/*
 * Copyright 2016-2019 52°North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.n52.svalbard.decode.stream.xml;

import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Optional;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.n52.iceland.util.XmlFactories;

import com.google.common.base.Strings;

/**
 * TODO JavaDoc
 *
 * @author Christian Autermann
 */
public abstract class AbstractElementXmlStreamReader extends XmlFactories implements ElementXmlStreamReader {

    private static final String PREFIX_XML = "xml";

    protected byte[] asBytes(StartElement start,
            XMLEventReader reader) throws XMLStreamException {
        return asString(start, reader).getBytes(StandardCharsets.UTF_8);
    }

    protected String asString(StartElement start,
            XMLEventReader reader) throws XMLStreamException {
        StringWriter stringWriter = new StringWriter();
        XMLEventWriter writer = outputFactory().createXMLEventWriter(stringWriter);

        // writer.add(eventFactory().createStartDocument());
        copy(reader, writer);
        // writer.add(eventFactory().createEndDocument());

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

    /**
     * Copies the content of current node of {@code reader} to {@code writer}.
     * Assumes that the current event is a START_ELEMENT and will proceed until
     * the corresponding END_ELEMENT is consumed.
     *
     * @param reader
     *            the reader
     * @param writer
     *            the writer
     *
     * @throws XMLStreamException
     *             if the copy operation fails
     */
    @SuppressWarnings("unchecked")
    protected void copy(XMLEventReader reader,
            XMLEventWriter writer) throws XMLStreamException {
        int depth = 0;

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

            if (event.isStartElement()) {
                StartElement elem = event.asStartElement();
                QName elementName = elem.getName();
                String elementPrefix = elementName.getPrefix();
                String elementNamespace = elementName.getNamespaceURI();

                // check if the current element's namespace is declared
                // this has to be done before the START_ELEMENT event is emitted
                // as this would put the namespace into the writer's context
                boolean writeElementNamespace = !elementPrefix.isEmpty() && !elementPrefix.equals(PREFIX_XML) && Strings
                        .isNullOrEmpty(writer.getNamespaceContext().getNamespaceURI(elementPrefix));

                // emit the element without any attributes or namespaces
                writer.add(eventFactory().createStartElement(elementName, null, null));

                // iterate over all namespace declaration to check if the
                // element namespace
                // is declared
                Iterator namespaces = elem.getNamespaces();
                while (namespaces.hasNext()) {
                    Namespace namespace = namespaces.next();
                    // checks if the namespace declaration matches the current
                    // element
                    if (elementPrefix.equals(namespace.getPrefix()) && elementNamespace.equals(namespace
                            .getNamespaceURI())) {
                        writeElementNamespace = false;
                    }
                    // declare the namespace
                    writer.add(eventFactory().createNamespace(Strings.nullToEmpty(namespace.getPrefix()), namespace
                            .getNamespaceURI()));
                }

                // if the there is no namespace declaration for the current
                // element, create one
                if (writeElementNamespace) {
                    writer.add(eventFactory().createNamespace(Strings.nullToEmpty(elementPrefix), elementNamespace));
                }

                // iterate over the attributes and check if there namespace is
                // declared, prior to emitting to ATTRIBUTE event
                Iterator attributes = elem.getAttributes();
                while (attributes.hasNext()) {
                    Attribute attribute = attributes.next();
                    String attributePrefix = attribute.getName().getPrefix();
                    String attributeNamespace = attribute.getName().getNamespaceURI();

                    if (!attributePrefix.isEmpty() && !attributePrefix.equals(PREFIX_XML) && Strings.isNullOrEmpty(
                            writer.getNamespaceContext().getNamespaceURI(attributePrefix))) {
                        writer.add(eventFactory().createNamespace(attributePrefix, attributeNamespace));
                    }
                    writer.add(eventFactory().createAttribute(attribute.getName(), attribute.getValue()));
                }
                ++depth;
            } else if (event.isEndElement()) {
                --depth;
                if (depth >= 0) {
                    writer.add(event);
                } else {
                    // we hit last closing tag
                    return;
                }
            } else {
                writer.add(event);
            }

        }
        throw eof();
    }

    protected static Optional getAttribute(StartElement event,
            QName name) {
        Attribute attr = event.getAttributeByName(name);
        return Optional.ofNullable(attr).map(Attribute::getValue);
    }

    protected static Optional getAttribute(StartElement event,
            String name) {
        return getAttribute(event, new QName(name));
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy