private static void processItem(final XMLStreamReader reader,
            final Writer writer, final String[] columns, final Filters filters,
            final Remappings remappings, final char separator,
            final boolean trim, final boolean join, final String parentElement,
            final Map<String, List<String>> values, final String itemName)
            throws XMLStreamException,
            IOException {
        final StringBuilder sb = new StringBuilder(1_024);

        while (reader.hasNext()) {
            switch (reader.next()) {
                case XMLStreamReader.START_ELEMENT:
                    final String currentElementPath = getParentName(
                            parentElement, reader.getLocalName());
                    processItem(reader, writer, columns, filters, remappings,
                            separator, trim, join, currentElementPath, values,
                            itemName);

                    break;
                case XMLStreamReader.CHARACTERS:
                    sb.append(reader.getText());

                    break;
                case XMLStreamReader.END_ELEMENT:
                    if ((parentElement).compareTo(itemName) == 0) {
                        final Map<String, String> singleValues = new HashMap<>(
                                columns.length);

                        for (Entry<String, List<String>> mapEntry : values.
                                entrySet()) {
                            singleValues.put(mapEntry.getKey(), prepareValue(
                                    mapEntry.getValue(), ", ", trim, join));
                        }

                        if (filters == null || filters.matchesFilters(
                                singleValues)) {
                            if (remappings != null) {
                                remappings.replaceValues(singleValues);
                            }

                            writeRow(writer, columns, singleValues, separator);
                        }
                    } else {
                        processValue(parentElement.replaceFirst(Pattern.quote(
                                itemName + "/"), ""), sb.toString(), values);
                    }
                    return;
            }
        }
    }