You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2020/01/15 16:12:11 UTC

[camel] 05/07: [CAMEL-14404] Provide a lightweight xml parser

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 8a8431c5d832d76698e0ad56abdb4daa6839bc67
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Jan 15 14:50:35 2020 +0100

    [CAMEL-14404] Provide a lightweight xml parser
---
 core/camel-xml-io/pom.xml                          |   73 +
 .../java/org/apache/camel/xml/in/BaseParser.java   |  245 ++
 .../java/org/apache/camel/xml/in/ModelParser.java  | 3033 ++++++++++++++++++
 .../java/org/apache/camel/xml/io/MXParser.java     | 3243 ++++++++++++++++++++
 .../org/apache/camel/xml/io/XmlPullParser.java     |  964 ++++++
 .../camel/xml/io/XmlPullParserException.java       |   55 +
 .../org/apache/camel/xml/io/XmlStreamReader.java   |  747 +++++
 .../camel/xml/io/XmlStreamReaderException.java     |  150 +
 .../org/apache/camel/xml/in/ModelParserTest.java   |   77 +
 .../src/test/resources/barInterceptorRoute.xml     |   31 +
 .../src/test/resources/barOnExceptionRoute.xml     |   37 +
 .../src/test/resources/barPolicyRoute.xml          |   37 +
 core/camel-xml-io/src/test/resources/barRest.xml   |   26 +
 core/camel-xml-io/src/test/resources/barRoute.xml  |   31 +
 .../src/test/resources/barUpdatedRoute.xml         |   34 +
 .../src/test/resources/convertBody.xml             |   25 +
 .../src/test/resources/dynamicRecipientList.xml    |   27 +
 core/camel-xml-io/src/test/resources/loop.xml      |   27 +
 core/camel-xml-io/src/test/resources/processor.xml |   25 +
 .../src/test/resources/processorWithFilter.xml     |   28 +
 .../test/resources/processorWithGroovyFilter.xml   |   28 +
 .../test/resources/processorWithHeaderFilter.xml   |   28 +
 .../test/resources/processorWithSimpleFilter.xml   |   28 +
 .../src/test/resources/resequencerBatch.xml        |   32 +
 .../src/test/resources/resequencerStream.xml       |   29 +
 .../camel-xml-io/src/test/resources/routeGroup.xml |   31 +
 .../src/test/resources/routeProperties.xml         |   34 +
 .../test/resources/routeWithBindyDataFormat.xml    |   30 +
 .../src/test/resources/routeWithChoice.xml         |   37 +
 .../routeWithCircuitBreakerLoadBalance.xml         |   33 +
 .../src/test/resources/routeWithCvsDataFormat.xml  |   30 +
 .../resources/routeWithFailoverLoadBalance.xml     |   33 +
 .../test/resources/routeWithFlatpackDataFormat.xml |   30 +
 .../src/test/resources/routeWithHL7DataFormat.xml  |   30 +
 .../src/test/resources/routeWithJSonDataFormat.xml |   30 +
 .../src/test/resources/routeWithJaxbDataFormat.xml |   30 +
 .../src/test/resources/routeWithLoadBalance.xml    |   30 +
 .../src/test/resources/routeWithNamespace.xml      |   34 +
 .../src/test/resources/routeWithRSSDataFormat.xml  |   30 +
 .../test/resources/routeWithRandomLoadBalance.xml  |   30 +
 .../test/resources/routeWithStickyLoadBalance.xml  |   34 +
 .../resources/routeWithTidyMarkupDataFormat.xml    |   30 +
 .../test/resources/routeWithTopicLoadBalance.xml   |   30 +
 .../resources/routeWithXMLSecurityDataFormat.xml   |   30 +
 .../test/resources/routeWithXStreamDataFormat.xml  |   30 +
 .../test/resources/routeWithZipFileDataFormat.xml  |   30 +
 .../src/test/resources/routingSlip.xml             |   27 +
 .../resources/routingSlipHeaderAndDelimiterSet.xml |   27 +
 .../src/test/resources/routingSlipHeaderSet.xml    |   27 +
 core/camel-xml-io/src/test/resources/saga.xml      |   31 +
 .../camel-xml-io/src/test/resources/scan-route.xml |   29 +
 core/camel-xml-io/src/test/resources/script.xml    |   28 +
 core/camel-xml-io/src/test/resources/setBody.xml   |   28 +
 core/camel-xml-io/src/test/resources/setHeader.xml |   28 +
 .../src/test/resources/setHeaderToConstant.xml     |   28 +
 .../camel-xml-io/src/test/resources/simpleRest.xml |   29 +
 .../src/test/resources/simpleRestToD.xml           |   29 +
 .../src/test/resources/simpleRoute.xml             |   31 +
 core/camel-xml-io/src/test/resources/splitter.xml  |   28 +
 .../src/test/resources/staticRecipientList.xml     |   27 +
 core/camel-xml-io/src/test/resources/transform.xml |   28 +
 core/pom.xml                                       |    1 +
 .../apache/camel/tooling/util/srcgen/Method.java   |    5 +-
 .../camel/maven/packaging/EndpointDslMojo.java     |    2 +-
 .../packaging/ModelXmlParserGeneratorMojo.java     |  717 +++++
 65 files changed, 10864 insertions(+), 2 deletions(-)

diff --git a/core/camel-xml-io/pom.xml b/core/camel-xml-io/pom.xml
new file mode 100644
index 0000000..f38185f
--- /dev/null
+++ b/core/camel-xml-io/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>core</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-xml-io</artifactId>
+
+    <name>Camel :: XML IO</name>
+    <description>Camel XML IO</description>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-engine</artifactId>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-package-maven-plugin</artifactId>
+                <version>${project.version}</version>
+                <executions>
+                    <execution>
+                        <id>generate</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>generate-xml-parser</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
new file mode 100644
index 0000000..b081e4a
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.xml.in;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.namespace.QName;
+
+import org.apache.camel.model.OtherAttributesAware;
+import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.xml.io.MXParser;
+import org.apache.camel.xml.io.XmlPullParser;
+import org.apache.camel.xml.io.XmlPullParserException;
+
+public class BaseParser {
+
+    protected final MXParser parser;
+    protected String namespace;
+
+    public BaseParser(InputStream input) throws IOException, XmlPullParserException {
+        this(input, null);
+    }
+
+    public BaseParser(Reader reader) throws IOException, XmlPullParserException {
+        this(reader, null);
+    }
+
+    public BaseParser(InputStream input, String namespace) throws IOException, XmlPullParserException {
+        this.parser = new MXParser();
+        this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+        this.parser.setInput(input, null);
+        this.namespace = namespace != null ? namespace : "";
+    }
+
+    public BaseParser(Reader reader, String namespace) throws IOException, XmlPullParserException {
+        this.parser = new MXParser();
+        this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+        this.parser.setInput(reader);
+        this.namespace = namespace != null ? namespace : "";
+    }
+
+    protected <T> T doParse(T definition,
+                            AttributeHandler<T> attributeHandler,
+                            ElementHandler<T> elementHandler,
+                            ValueHandler<T> valueHandler)
+            throws IOException, XmlPullParserException {
+        for (int i = 0; i < parser.getAttributeCount(); i++) {
+            String name = parser.getAttributeName(i);
+            String ns = parser.getAttributeNamespace(i);
+            String val = parser.getAttributeValue(i);
+            if (Objects.equals(ns, "") || Objects.equals(ns, namespace)) {
+                if (attributeHandler == null || !attributeHandler.accept(definition, name, val)) {
+                    handleUnexpectedAttribute(namespace, name);
+                }
+            } else {
+                handleOtherAttribute(definition, name, ns, val);
+            }
+        }
+        while (true) {
+            int event = parser.next();
+            if (event == XmlPullParser.TEXT) {
+                if (!parser.isWhitespace()) {
+                    valueHandler.accept(definition, parser.getText());
+                }
+            } else if (event == XmlPullParser.START_TAG) {
+                String ns = parser.getNamespace();
+                String name = parser.getName();
+                if (Objects.equals(ns, namespace)) {
+                    if (elementHandler == null || !elementHandler.accept(definition, name)) {
+                        handleUnexpectedElement(namespace, name);
+                    }
+                } else {
+                    handleUnexpectedElement(ns, name);
+                }
+            } else if (event == XmlPullParser.END_TAG) {
+                return definition;
+            } else {
+                throw new XmlPullParserException("expected START_TAG or END_TAG not "
+                        + XmlPullParser.TYPES[ event ], parser, null);
+            }
+        }
+    }
+
+    protected Class<?> asClass(String val) throws XmlPullParserException {
+        try {
+            return Class.forName(val);
+        } catch (ClassNotFoundException e) {
+            throw new XmlPullParserException("Unable to load class " + val, parser, e);
+        }
+    }
+
+    protected Class<?>[] asClassArray(String val) throws XmlPullParserException {
+        String[] vals = val.split(" ");
+        Class<?>[] cls = new Class<?>[vals.length];
+        for (int i = 0; i < vals.length; i++) {
+            cls[i] = asClass(vals[i]);
+        }
+        return cls;
+    }
+
+    protected byte[] asByteArray(String val) {
+        return Base64.getDecoder().decode(val);
+    }
+
+    protected List<String> asStringList(String val) {
+        return new ArrayList<>(Arrays.asList(val.split(" ")));
+    }
+
+    protected Set<String> asStringSet(String val) {
+        return new LinkedHashSet<>(Arrays.asList(val.split(" ")));
+    }
+
+    protected <T> void doAdd(T element, List<T> existing, Consumer<List<T>> setter) {
+        if (existing == null) {
+            existing = new ArrayList<>();
+            setter.accept(existing);
+        }
+        existing.add(element);
+    }
+
+    protected <V, B> B unmarshal(XmlAdapter<V,B> adapter, V value) throws XmlPullParserException {
+        try {
+            return adapter.unmarshal(value);
+        } catch (Exception e) {
+            throw new XmlPullParserException("Unable to unmarshal value", parser, e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T> void doAdd(T element, T[] existing, Consumer<T[]> setter) {
+        int len = existing != null ? existing.length : 0;
+        T[] newArray = (T[]) Array.newInstance(element.getClass(), len + 1);
+        if (len > 0) {
+            System.arraycopy(existing, 0, newArray, 0, len);
+        }
+        newArray[len] = element;
+        setter.accept(newArray);
+    }
+
+    protected String doParseText() throws IOException, XmlPullParserException {
+        String s = "";
+        int e = parser.next();
+        if (e == XmlPullParser.TEXT) {
+            s = parser.getText();
+            e = parser.next();
+        }
+        if (e != XmlPullParser.END_TAG) {
+            throw new XmlPullParserException("Expected text element");
+        }
+        return s;
+    }
+
+    protected boolean handleUnexpectedAttribute(String namespace, String name) throws XmlPullParserException {
+        throw new XmlPullParserException("Unexpected attribute '{" + namespace + "}" + name + "'");
+    }
+
+    protected boolean handleUnexpectedElement(String namespace, String name) throws XmlPullParserException {
+        throw new XmlPullParserException("Unexpected element '{" + namespace + "}" + name + "'");
+    }
+
+    protected void handleUnexpectedText(String text) throws XmlPullParserException {
+        throw new XmlPullParserException("Unexpected text '" + text + "'");
+    }
+
+    protected void expectTag(String name) throws XmlPullParserException, IOException {
+        if (parser.nextTag() != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("Expected starting tag '{" + namespace + "}" + name + "', read ending tag '{" +
+                    parser.getNamespace() + "}" + parser.getName() + "' instead");
+        }
+        if (!Objects.equals(name, parser.getName())
+                || !Objects.equals(namespace, parser.getNamespace())) {
+            throw new XmlPullParserException("Expected starting tag '{" + namespace + "}" + name + "', read starting tag '{" +
+                    parser.getNamespace() + "}" + parser.getName() + "' instead");
+        }
+    }
+
+    protected void handleOtherAttribute(Object definition, String name, String ns, String val) throws XmlPullParserException {
+        if (definition instanceof OtherAttributesAware) {
+            Map<QName, Object> others = ((OtherAttributesAware) definition).getOtherAttributes();
+            if (others == null) {
+                others = new LinkedHashMap<>();
+                ((OtherAttributesAware) definition).setOtherAttributes(others);
+            }
+            others.put(new QName(ns, name), val);
+        } else {
+            throw new XmlPullParserException("Unsupported attribute '{" + ns + "}" + name + "'");
+        }
+    }
+
+    protected <T> AttributeHandler<T> noAttributeHandler() {
+        return null;
+    }
+
+    protected <T> ElementHandler<T> noElementHandler() {
+        return (def, name) -> handleUnexpectedElement(namespace, name);
+    }
+
+    protected <T> ValueHandler<T> noValueHandler() {
+        return (def, text) -> handleUnexpectedText(text);
+    }
+
+    protected <T extends ExpressionDefinition> ValueHandler<T> expressionDefinitionValueHandler() {
+        return ExpressionDefinition::setExpression;
+    }
+
+    interface AttributeHandler<T> {
+        boolean accept(T definition, String name, String value) throws IOException, XmlPullParserException;
+    }
+
+    interface ElementHandler<T> {
+        boolean accept(T definition, String name) throws IOException, XmlPullParserException;
+    }
+
+    interface ValueHandler<T> {
+        void accept(T definition, String value) throws IOException, XmlPullParserException;
+    }
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java
new file mode 100644
index 0000000..1b4ed77
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/ModelParser.java
@@ -0,0 +1,3033 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.xml.in;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Generated;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ShutdownRoute;
+import org.apache.camel.ShutdownRunningTask;
+import org.apache.camel.model.*;
+import org.apache.camel.model.cloud.*;
+import org.apache.camel.model.config.BatchResequencerConfig;
+import org.apache.camel.model.config.ResequencerConfig;
+import org.apache.camel.model.config.StreamResequencerConfig;
+import org.apache.camel.model.dataformat.*;
+import org.apache.camel.model.language.*;
+import org.apache.camel.model.loadbalancer.*;
+import org.apache.camel.model.rest.*;
+import org.apache.camel.model.transformer.*;
+import org.apache.camel.model.validator.*;
+import org.apache.camel.util.concurrent.ThreadPoolRejectedPolicy;
+import org.apache.camel.xml.io.XmlPullParserException;
+
+@SuppressWarnings("unused")
+@Generated("org.apache.camel.maven.packaging.ModelXmlParserGeneratorMojo")
+public class ModelParser extends BaseParser {
+
+    public ModelParser(
+            InputStream input)
+            throws IOException, XmlPullParserException {
+        super(input);
+    }
+    public ModelParser(Reader reader) throws IOException, XmlPullParserException {
+        super(reader);
+    }
+    public ModelParser(
+            InputStream input,
+            String namespace)
+            throws IOException, XmlPullParserException {
+        super(input, namespace);
+    }
+    public ModelParser(
+            Reader reader,
+            String namespace)
+            throws IOException, XmlPullParserException {
+        super(reader, namespace);
+    }
+    protected AggregateDefinition doParseAggregateDefinition() throws IOException, XmlPullParserException {
+        return doParse(new AggregateDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "aggregateControllerRef": def.setAggregateControllerRef(val); break;
+                case "aggregationRepositoryRef": def.setAggregationRepositoryRef(val); break;
+                case "closeCorrelationKeyOnCompletion": def.setCloseCorrelationKeyOnCompletion(val); break;
+                case "completeAllOnStop": def.setCompleteAllOnStop(val); break;
+                case "completionFromBatchConsumer": def.setCompletionFromBatchConsumer(val); break;
+                case "completionInterval": def.setCompletionInterval(val); break;
+                case "completionOnNewCorrelationGroup": def.setCompletionOnNewCorrelationGroup(val); break;
+                case "completionSize": def.setCompletionSize(val); break;
+                case "completionTimeout": def.setCompletionTimeout(val); break;
+                case "completionTimeoutCheckerInterval": def.setCompletionTimeoutCheckerInterval(val); break;
+                case "discardOnAggregationFailure": def.setDiscardOnAggregationFailure(val); break;
+                case "discardOnCompletionTimeout": def.setDiscardOnCompletionTimeout(val); break;
+                case "eagerCheckCompletion": def.setEagerCheckCompletion(val); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "forceCompletionOnStop": def.setForceCompletionOnStop(val); break;
+                case "ignoreInvalidCorrelationKeys": def.setIgnoreInvalidCorrelationKeys(val); break;
+                case "optimisticLocking": def.setOptimisticLocking(val); break;
+                case "parallelProcessing": def.setParallelProcessing(val); break;
+                case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+                case "strategyMethodName": def.setStrategyMethodName(val); break;
+                case "strategyRef": def.setStrategyRef(val); break;
+                case "timeoutCheckerExecutorServiceRef": def.setTimeoutCheckerExecutorServiceRef(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "completionPredicate": def.setCompletionPredicate(doParseExpressionSubElementDefinition()); break;
+                case "completionSizeExpression": def.setCompletionSizeExpression(doParseExpressionSubElementDefinition()); break;
+                case "completionTimeoutExpression": def.setCompletionTimeoutExpression(doParseExpressionSubElementDefinition()); break;
+                case "correlationExpression": def.setCorrelationExpression(doParseExpressionSubElementDefinition()); break;
+                case "optimisticLockRetryPolicy": def.setOptimisticLockRetryPolicyDefinition(doParseOptimisticLockRetryPolicyDefinition()); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ExpressionSubElementDefinition doParseExpressionSubElementDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ExpressionSubElementDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpressionType(v);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected OptimisticLockRetryPolicyDefinition doParseOptimisticLockRetryPolicyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OptimisticLockRetryPolicyDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "exponentialBackOff": def.setExponentialBackOff(val); break;
+                case "maximumRetries": def.setMaximumRetries(val); break;
+                case "maximumRetryDelay": def.setMaximumRetryDelay(val); break;
+                case "randomBackOff": def.setRandomBackOff(val); break;
+                case "retryDelay": def.setRetryDelay(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected <T extends OutputDefinition> ElementHandler<T> outputDefinitionElementHandler() {
+        return (def, key) -> {
+            ProcessorDefinition v = doParseProcessorDefinitionRef(key);
+            if (v != null) { 
+                doAdd(v, def.getOutputs(), def::setOutputs);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        };
+    }
+    protected OutputDefinition doParseOutputDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OutputDefinition(), 
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected <T extends ProcessorDefinition> AttributeHandler<T> processorDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            if ("inheritErrorHandler".equals(key)) {
+                def.setInheritErrorHandler(Boolean.valueOf(val));
+                return true;
+            }
+            return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+        };
+    }
+    protected <T extends OptionalIdentifiedDefinition> AttributeHandler<T> optionalIdentifiedDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "customId": def.setCustomId(Boolean.valueOf(val)); break;
+                case "id": def.setId(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected <T extends OptionalIdentifiedDefinition> ElementHandler<T> optionalIdentifiedDefinitionElementHandler() {
+        return (def, key) -> {
+            if ("description".equals(key)) {
+                def.setDescription(doParseDescriptionDefinition());
+                return true;
+            }
+            return false;
+        };
+    }
+    protected DescriptionDefinition doParseDescriptionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DescriptionDefinition(), (def, key, val) -> {
+            if ("lang".equals(key)) {
+                def.setLang(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), (def, val) -> def.setText(val));
+    }
+    protected BeanDefinition doParseBeanDefinition() throws IOException, XmlPullParserException {
+        return doParse(new BeanDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "beanType": def.setBeanType(val); break;
+                case "cache": def.setCache(val); break;
+                case "method": def.setMethod(val); break;
+                case "ref": def.setRef(val); break;
+                case "scope": def.setScope(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected CatchDefinition doParseCatchDefinition() throws IOException, XmlPullParserException {
+        return doParse(new CatchDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "exception": doAdd(doParseText(), def.getExceptions(), def::setExceptions); break;
+                case "onWhen": def.setOnWhen(doParseWhenDefinition()); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected WhenDefinition doParseWhenDefinition() throws IOException, XmlPullParserException {
+        return doParse(new WhenDefinition(), 
+            processorDefinitionAttributeHandler(),  outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected ChoiceDefinition doParseChoiceDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ChoiceDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "when": doAdd(doParseWhenDefinition(), def.getWhenClauses(), def::setWhenClauses); break;
+                case "whenSkipSendToEndpoint": doAdd(doParseWhenSkipSendToEndpointDefinition(), def.getWhenClauses(), def::setWhenClauses); break;
+                case "otherwise": def.setOtherwise(doParseOtherwiseDefinition()); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected OtherwiseDefinition doParseOtherwiseDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OtherwiseDefinition(),
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected CircuitBreakerDefinition doParseCircuitBreakerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new CircuitBreakerDefinition(), (def, key, val) -> {
+            if ("configurationRef".equals(key)) {
+                def.setConfigurationRef(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, (def, key) -> {
+            switch (key) {
+                case "hystrixConfiguration": def.setHystrixConfiguration(doParseHystrixConfigurationDefinition()); break;
+                case "resilience4jConfiguration": def.setResilience4jConfiguration(doParseResilience4jConfigurationDefinition()); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected HystrixConfigurationDefinition doParseHystrixConfigurationDefinition() throws IOException, XmlPullParserException {
+        return doParse(new HystrixConfigurationDefinition(),
+            hystrixConfigurationCommonAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected Resilience4jConfigurationDefinition doParseResilience4jConfigurationDefinition() throws IOException, XmlPullParserException {
+        return doParse(new Resilience4jConfigurationDefinition(),
+            resilience4jConfigurationCommonAttributeHandler(), resilience4jConfigurationCommonElementHandler(), noValueHandler());
+    }
+    protected ClaimCheckDefinition doParseClaimCheckDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ClaimCheckDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "filter": def.setFilter(val); break;
+                case "key": def.setKey(val); break;
+                case "operation": def.setOperation(val); break;
+                case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+                case "strategyRef": def.setAggregationStrategyRef(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ContextScanDefinition doParseContextScanDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ContextScanDefinition(), (def, key, val) -> {
+            if ("includeNonSingletons".equals(key)) {
+                def.setIncludeNonSingletons(val);
+                return true;
+            }
+            return false;
+        }, (def, key) -> {
+            switch (key) {
+                case "excludes": doAdd(doParseText(), def.getExcludes(), def::setExcludes); break;
+                case "includes": doAdd(doParseText(), def.getIncludes(), def::setIncludes); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ConvertBodyDefinition doParseConvertBodyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ConvertBodyDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "charset": def.setCharset(val); break;
+                case "type": def.setType(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected <T extends DataFormatDefinition> AttributeHandler<T> dataFormatDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            if ("contentTypeHeader".equals(key)) {
+                def.setContentTypeHeader(val);
+                return true;
+            }
+            return identifiedTypeAttributeHandler().accept(def, key, val);
+        };
+    }
+    protected DataFormatDefinition doParseDataFormatDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DataFormatDefinition(), dataFormatDefinitionAttributeHandler(),  noElementHandler(), noValueHandler());
+    }
+    protected <T extends IdentifiedType> AttributeHandler<T> identifiedTypeAttributeHandler() {
+        return (def, key, val) -> {
+            if ("id".equals(key)) {
+                def.setId(val);
+                return true;
+            }
+            return false;
+        };
+    }
+    protected DelayDefinition doParseDelayDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DelayDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "asyncDelayed": def.setAsyncDelayed(val); break;
+                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
+        return (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpression(v);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        };
+    }
+    protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "id": def.setId(val); break;
+                case "trim": def.setTrim(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(),  noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected DynamicRouterDefinition doParseDynamicRouterDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DynamicRouterDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "cacheSize": def.setCacheSize(val); break;
+                case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+                case "uriDelimiter": def.setUriDelimiter(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected EnrichDefinition doParseEnrichDefinition() throws IOException, XmlPullParserException {
+        return doParse(new EnrichDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "aggregateOnException": def.setAggregateOnException(val); break;
+                case "cacheSize": def.setCacheSize(val); break;
+                case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+                case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+                case "strategyMethodAllowNull": def.setAggregationStrategyMethodAllowNull(val); break;
+                case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+                case "strategyRef": def.setAggregationStrategyRef(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected FilterDefinition doParseFilterDefinition() throws IOException, XmlPullParserException {
+        return doParse(new FilterDefinition(),
+            processorDefinitionAttributeHandler(), outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected <T extends OutputExpressionNode> ElementHandler<T> outputExpressionNodeElementHandler() {
+        return (def, key) -> {
+            ProcessorDefinition v = doParseProcessorDefinitionRef(key);
+            if (v != null) { 
+                doAdd(v, def.getOutputs(), def::setOutputs);
+                return true;
+            }
+            return expressionNodeElementHandler().accept(def, key);
+        };
+    }
+    protected FinallyDefinition doParseFinallyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new FinallyDefinition(),
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected FromDefinition doParseFromDefinition() throws IOException, XmlPullParserException {
+        return doParse(new FromDefinition(), (def, key, val) -> {
+            if ("uri".equals(key)) {
+                def.setUri(val);
+                return true;
+            }
+            return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected GlobalOptionDefinition doParseGlobalOptionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new GlobalOptionDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "key": def.setKey(val); break;
+                case "value": def.setValue(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected GlobalOptionsDefinition doParseGlobalOptionsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new GlobalOptionsDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            if ("globalOption".equals(key)) {
+                doAdd(doParseGlobalOptionDefinition(), def.getGlobalOptions(), def::setGlobalOptions);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected <T extends HystrixConfigurationCommon> AttributeHandler<T> hystrixConfigurationCommonAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "allowMaximumSizeToDivergeFromCoreSize": def.setAllowMaximumSizeToDivergeFromCoreSize(val); break;
+                case "circuitBreakerEnabled": def.setCircuitBreakerEnabled(val); break;
+                case "circuitBreakerErrorThresholdPercentage": def.setCircuitBreakerErrorThresholdPercentage(val); break;
+                case "circuitBreakerForceClosed": def.setCircuitBreakerForceClosed(val); break;
+                case "circuitBreakerForceOpen": def.setCircuitBreakerForceOpen(val); break;
+                case "circuitBreakerRequestVolumeThreshold": def.setCircuitBreakerRequestVolumeThreshold(val); break;
+                case "circuitBreakerSleepWindowInMilliseconds": def.setCircuitBreakerSleepWindowInMilliseconds(val); break;
+                case "corePoolSize": def.setCorePoolSize(val); break;
+                case "executionIsolationSemaphoreMaxConcurrentRequests": def.setExecutionIsolationSemaphoreMaxConcurrentRequests(val); break;
+                case "executionIsolationStrategy": def.setExecutionIsolationStrategy(val); break;
+                case "executionIsolationThreadInterruptOnTimeout": def.setExecutionIsolationThreadInterruptOnTimeout(val); break;
+                case "executionTimeoutEnabled": def.setExecutionTimeoutEnabled(val); break;
+                case "executionTimeoutInMilliseconds": def.setExecutionTimeoutInMilliseconds(val); break;
+                case "fallbackEnabled": def.setFallbackEnabled(val); break;
+                case "fallbackIsolationSemaphoreMaxConcurrentRequests": def.setFallbackIsolationSemaphoreMaxConcurrentRequests(val); break;
+                case "groupKey": def.setGroupKey(val); break;
+                case "keepAliveTime": def.setKeepAliveTime(val); break;
+                case "maxQueueSize": def.setMaxQueueSize(val); break;
+                case "maximumSize": def.setMaximumSize(val); break;
+                case "metricsHealthSnapshotIntervalInMilliseconds": def.setMetricsHealthSnapshotIntervalInMilliseconds(val); break;
+                case "metricsRollingPercentileBucketSize": def.setMetricsRollingPercentileBucketSize(val); break;
+                case "metricsRollingPercentileEnabled": def.setMetricsRollingPercentileEnabled(val); break;
+                case "metricsRollingPercentileWindowBuckets": def.setMetricsRollingPercentileWindowBuckets(val); break;
+                case "metricsRollingPercentileWindowInMilliseconds": def.setMetricsRollingPercentileWindowInMilliseconds(val); break;
+                case "metricsRollingStatisticalWindowBuckets": def.setMetricsRollingStatisticalWindowBuckets(val); break;
+                case "metricsRollingStatisticalWindowInMilliseconds": def.setMetricsRollingStatisticalWindowInMilliseconds(val); break;
+                case "queueSizeRejectionThreshold": def.setQueueSizeRejectionThreshold(val); break;
+                case "requestLogEnabled": def.setRequestLogEnabled(val); break;
+                case "threadPoolKey": def.setThreadPoolKey(val); break;
+                case "threadPoolRollingNumberStatisticalWindowBuckets": def.setThreadPoolRollingNumberStatisticalWindowBuckets(val); break;
+                case "threadPoolRollingNumberStatisticalWindowInMilliseconds": def.setThreadPoolRollingNumberStatisticalWindowInMilliseconds(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected HystrixConfigurationCommon doParseHystrixConfigurationCommon() throws IOException, XmlPullParserException {
+        return doParse(new HystrixConfigurationCommon(), hystrixConfigurationCommonAttributeHandler(),  noElementHandler(), noValueHandler());
+    }
+    protected IdempotentConsumerDefinition doParseIdempotentConsumerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new IdempotentConsumerDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "completionEager": def.setCompletionEager(val); break;
+                case "eager": def.setEager(val); break;
+                case "messageIdRepositoryRef": def.setMessageIdRepositoryRef(val); break;
+                case "removeOnFailure": def.setRemoveOnFailure(val); break;
+                case "skipDuplicate": def.setSkipDuplicate(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected InOnlyDefinition doParseInOnlyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InOnlyDefinition(),
+            sendDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected <T extends SendDefinition> AttributeHandler<T> sendDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            if ("uri".equals(key)) {
+                def.setUri(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        };
+    }
+    protected InOutDefinition doParseInOutDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InOutDefinition(),
+            sendDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected InputTypeDefinition doParseInputTypeDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InputTypeDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "urn": def.setUrn(val); break;
+                case "validate": def.setValidate(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected InterceptDefinition doParseInterceptDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InterceptDefinition(), 
+            processorDefinitionAttributeHandler(),  outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected InterceptFromDefinition doParseInterceptFromDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InterceptFromDefinition(), (def, key, val) -> {
+            if ("uri".equals(key)) {
+                def.setUri(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected InterceptSendToEndpointDefinition doParseInterceptSendToEndpointDefinition() throws IOException, XmlPullParserException {
+        return doParse(new InterceptSendToEndpointDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "afterUri": def.setAfterUri(val); break;
+                case "skipSendToOriginalEndpoint": def.setSkipSendToOriginalEndpoint(val); break;
+                case "uri": def.setUri(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected LoadBalanceDefinition doParseLoadBalanceDefinition() throws IOException, XmlPullParserException {
+        return doParse(new LoadBalanceDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "failover": def.setLoadBalancerType(doParseFailoverLoadBalancerDefinition()); break;
+                case "random": def.setLoadBalancerType(doParseRandomLoadBalancerDefinition()); break;
+                case "customLoadBalancer": def.setLoadBalancerType(doParseCustomLoadBalancerDefinition()); break;
+                case "roundRobin": def.setLoadBalancerType(doParseRoundRobinLoadBalancerDefinition()); break;
+                case "sticky": def.setLoadBalancerType(doParseStickyLoadBalancerDefinition()); break;
+                case "topic": def.setLoadBalancerType(doParseTopicLoadBalancerDefinition()); break;
+                case "weighted": def.setLoadBalancerType(doParseWeightedLoadBalancerDefinition()); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected LoadBalancerDefinition doParseLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new LoadBalancerDefinition(), 
+            identifiedTypeAttributeHandler(),  noElementHandler(), noValueHandler());
+    }
+    protected LogDefinition doParseLogDefinition() throws IOException, XmlPullParserException {
+        return doParse(new LogDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "logName": def.setLogName(val); break;
+                case "loggerRef": def.setLoggerRef(val); break;
+                case "loggingLevel": def.setLoggingLevel(val); break;
+                case "marker": def.setMarker(val); break;
+                case "message": def.setMessage(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected LoopDefinition doParseLoopDefinition() throws IOException, XmlPullParserException {
+        return doParse(new LoopDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "copy": def.setCopy(val); break;
+                case "doWhile": def.setDoWhile(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected MarshalDefinition doParseMarshalDefinition() throws IOException, XmlPullParserException {
+        return doParse(new MarshalDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+            if (v != null) { 
+                def.setDataFormatType(v);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected MulticastDefinition doParseMulticastDefinition() throws IOException, XmlPullParserException {
+        return doParse(new MulticastDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "onPrepareRef": def.setOnPrepareRef(val); break;
+                case "parallelAggregate": def.setParallelAggregate(val); break;
+                case "parallelProcessing": def.setParallelProcessing(val); break;
+                case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+                case "stopOnAggregateException": def.setStopOnAggregateException(val); break;
+                case "stopOnException": def.setStopOnException(val); break;
+                case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+                case "strategyMethodName": def.setStrategyMethodName(val); break;
+                case "strategyRef": def.setStrategyRef(val); break;
+                case "streaming": def.setStreaming(val); break;
+                case "timeout": def.setTimeout(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected OnCompletionDefinition doParseOnCompletionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OnCompletionDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "mode": def.setMode(OnCompletionMode.valueOf(val)); break;
+                case "onCompleteOnly": def.setOnCompleteOnly(val); break;
+                case "onFailureOnly": def.setOnFailureOnly(val); break;
+                case "parallelProcessing": def.setParallelProcessing(val); break;
+                case "useOriginalMessage": def.setUseOriginalMessage(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("onWhen".equals(key)) {
+                def.setOnWhen(doParseWhenDefinition());
+                return true;
+            }
+            return outputDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected OnExceptionDefinition doParseOnExceptionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OnExceptionDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "onExceptionOccurredRef": def.setOnExceptionOccurredRef(val); break;
+                case "onRedeliveryRef": def.setOnRedeliveryRef(val); break;
+                case "redeliveryPolicyRef": def.setRedeliveryPolicyRef(val); break;
+                case "useOriginalBody": def.setUseOriginalBody(val); break;
+                case "useOriginalMessage": def.setUseOriginalMessage(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "continued": def.setContinued(doParseExpressionSubElementDefinition()); break;
+                case "exception": doAdd(doParseText(), def.getExceptions(), def::setExceptions); break;
+                case "handled": def.setHandled(doParseExpressionSubElementDefinition()); break;
+                case "onWhen": def.setOnWhen(doParseWhenDefinition()); break;
+                case "redeliveryPolicy": def.setRedeliveryPolicyType(doParseRedeliveryPolicyDefinition()); break;
+                case "retryWhile": def.setRetryWhile(doParseExpressionSubElementDefinition()); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RedeliveryPolicyDefinition doParseRedeliveryPolicyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RedeliveryPolicyDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "allowRedeliveryWhileStopping": def.setAllowRedeliveryWhileStopping(val); break;
+                case "asyncDelayedRedelivery": def.setAsyncDelayedRedelivery(val); break;
+                case "backOffMultiplier": def.setBackOffMultiplier(val); break;
+                case "collisionAvoidanceFactor": def.setCollisionAvoidanceFactor(val); break;
+                case "delayPattern": def.setDelayPattern(val); break;
+                case "disableRedelivery": def.setDisableRedelivery(val); break;
+                case "exchangeFormatterRef": def.setExchangeFormatterRef(val); break;
+                case "logContinued": def.setLogContinued(val); break;
+                case "logExhausted": def.setLogExhausted(val); break;
+                case "logExhaustedMessageBody": def.setLogExhaustedMessageBody(val); break;
+                case "logExhaustedMessageHistory": def.setLogExhaustedMessageHistory(val); break;
+                case "logHandled": def.setLogHandled(val); break;
+                case "logNewException": def.setLogNewException(val); break;
+                case "logRetryAttempted": def.setLogRetryAttempted(val); break;
+                case "logRetryStackTrace": def.setLogRetryStackTrace(val); break;
+                case "logStackTrace": def.setLogStackTrace(val); break;
+                case "maximumRedeliveries": def.setMaximumRedeliveries(val); break;
+                case "maximumRedeliveryDelay": def.setMaximumRedeliveryDelay(val); break;
+                case "redeliveryDelay": def.setRedeliveryDelay(val); break;
+                case "retriesExhaustedLogLevel": def.setRetriesExhaustedLogLevel(val); break;
+                case "retryAttemptedLogInterval": def.setRetryAttemptedLogInterval(val); break;
+                case "retryAttemptedLogLevel": def.setRetryAttemptedLogLevel(val); break;
+                case "useCollisionAvoidance": def.setUseCollisionAvoidance(val); break;
+                case "useExponentialBackOff": def.setUseExponentialBackOff(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected OnFallbackDefinition doParseOnFallbackDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OnFallbackDefinition(), (def, key, val) -> {
+            if ("fallbackViaNetwork".equals(key)) {
+                def.setFallbackViaNetwork(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected OutputTypeDefinition doParseOutputTypeDefinition() throws IOException, XmlPullParserException {
+        return doParse(new OutputTypeDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "urn": def.setUrn(val); break;
+                case "validate": def.setValidate(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected PackageScanDefinition doParsePackageScanDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PackageScanDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "excludes": doAdd(doParseText(), def.getExcludes(), def::setExcludes); break;
+                case "includes": doAdd(doParseText(), def.getIncludes(), def::setIncludes); break;
+                case "package": doAdd(doParseText(), def.getPackages(), def::setPackages); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected PipelineDefinition doParsePipelineDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PipelineDefinition(),
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected PolicyDefinition doParsePolicyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PolicyDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected PollEnrichDefinition doParsePollEnrichDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PollEnrichDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "aggregateOnException": def.setAggregateOnException(val); break;
+                case "cacheSize": def.setCacheSize(val); break;
+                case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+                case "strategyMethodAllowNull": def.setAggregationStrategyMethodAllowNull(val); break;
+                case "strategyMethodName": def.setAggregationStrategyMethodName(val); break;
+                case "strategyRef": def.setAggregationStrategyRef(val); break;
+                case "timeout": def.setTimeout(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected ProcessDefinition doParseProcessDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ProcessDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected PropertyDefinition doParsePropertyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PropertyDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "key": def.setKey(val); break;
+                case "value": def.setValue(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected PropertyDefinitions doParsePropertyDefinitions() throws IOException, XmlPullParserException {
+        return doParse(new PropertyDefinitions(),
+            noAttributeHandler(), (def, key) -> {
+            if ("properties".equals(key)) {
+                doAdd(doParsePropertyDefinition(), def.getProperties(), def::setProperties);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected RecipientListDefinition doParseRecipientListDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RecipientListDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "cacheSize": def.setCacheSize(val); break;
+                case "delimiter": def.setDelimiter(val); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+                case "onPrepareRef": def.setOnPrepareRef(val); break;
+                case "parallelAggregate": def.setParallelAggregate(val); break;
+                case "parallelProcessing": def.setParallelProcessing(val); break;
+                case "shareUnitOfWork": def.setShareUnitOfWork(val); break;
+                case "stopOnAggregateException": def.setStopOnAggregateException(val); break;
+                case "stopOnException": def.setStopOnException(val); break;
+                case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(val); break;
+                case "strategyMethodName": def.setStrategyMethodName(val); break;
+                case "strategyRef": def.setStrategyRef(val); break;
+                case "streaming": def.setStreaming(val); break;
+                case "timeout": def.setTimeout(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected RemoveHeaderDefinition doParseRemoveHeaderDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RemoveHeaderDefinition(), (def, key, val) -> {
+            if ("headerName".equals(key)) {
+                def.setHeaderName(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected RemoveHeadersDefinition doParseRemoveHeadersDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RemoveHeadersDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "excludePattern": def.setExcludePattern(val); break;
+                case "pattern": def.setPattern(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected RemovePropertiesDefinition doParseRemovePropertiesDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RemovePropertiesDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "excludePattern": def.setExcludePattern(val); break;
+                case "pattern": def.setPattern(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected RemovePropertyDefinition doParseRemovePropertyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RemovePropertyDefinition(), (def, key, val) -> {
+            if ("propertyName".equals(key)) {
+                def.setPropertyName(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ResequenceDefinition doParseResequenceDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ResequenceDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "batch-config": def.setResequencerConfig(doParseBatchResequencerConfig()); break;
+                case "stream-config": def.setResequencerConfig(doParseStreamResequencerConfig()); break;
+                default: 
+                    ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+                    if (v != null) { 
+                        def.setExpression(v);
+                        return true;
+                    }
+                    return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected <T extends Resilience4jConfigurationCommon> AttributeHandler<T> resilience4jConfigurationCommonAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "automaticTransitionFromOpenToHalfOpenEnabled": def.setAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean.valueOf(val)); break;
+                case "circuitBreakerRef": def.setCircuitBreakerRef(val); break;
+                case "configRef": def.setConfigRef(val); break;
+                case "failureRateThreshold": def.setFailureRateThreshold(Float.valueOf(val)); break;
+                case "minimumNumberOfCalls": def.setMinimumNumberOfCalls(Integer.valueOf(val)); break;
+                case "permittedNumberOfCallsInHalfOpenState": def.setPermittedNumberOfCallsInHalfOpenState(Integer.valueOf(val)); break;
+                case "slidingWindowSize": def.setSlidingWindowSize(Integer.valueOf(val)); break;
+                case "slidingWindowType": def.setSlidingWindowType(val); break;
+                case "slowCallDurationThreshold": def.setSlowCallDurationThreshold(Integer.valueOf(val)); break;
+                case "slowCallRateThreshold": def.setSlowCallRateThreshold(Float.valueOf(val)); break;
+                case "waitDurationInOpenState": def.setWaitDurationInOpenState(Integer.valueOf(val)); break;
+                case "writableStackTraceEnabled": def.setWritableStackTraceEnabled(Boolean.valueOf(val)); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected <T extends Resilience4jConfigurationCommon> ElementHandler<T> resilience4jConfigurationCommonElementHandler() {
+        return (def, key) -> {
+            switch (key) {
+                case "bulkheadEnabled": def.setBulkheadEnabled(Boolean.valueOf(doParseText())); break;
+                case "bulkheadMaxConcurrentCalls": def.setBulkheadMaxConcurrentCalls(Integer.valueOf(doParseText())); break;
+                case "bulkheadMaxWaitDuration": def.setBulkheadMaxWaitDuration(Integer.valueOf(doParseText())); break;
+                case "timeoutCancelRunningFuture": def.setTimeoutCancelRunningFuture(Boolean.valueOf(doParseText())); break;
+                case "timeoutDuration": def.setTimeoutDuration(Integer.valueOf(doParseText())); break;
+                case "timeoutEnabled": def.setTimeoutEnabled(Boolean.valueOf(doParseText())); break;
+                case "timeoutExecutorServiceRef": def.setTimeoutExecutorServiceRef(doParseText()); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected Resilience4jConfigurationCommon doParseResilience4jConfigurationCommon() throws IOException, XmlPullParserException {
+        return doParse(new Resilience4jConfigurationCommon(), resilience4jConfigurationCommonAttributeHandler(), resilience4jConfigurationCommonElementHandler(), noValueHandler());
+    }
+    protected RestContextRefDefinition doParseRestContextRefDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestContextRefDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RollbackDefinition doParseRollbackDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RollbackDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "markRollbackOnly": def.setMarkRollbackOnly(val); break;
+                case "markRollbackOnlyLast": def.setMarkRollbackOnlyLast(val); break;
+                case "message": def.setMessage(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected RouteBuilderDefinition doParseRouteBuilderDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RouteBuilderDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return identifiedTypeAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RouteContextRefDefinition doParseRouteContextRefDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RouteContextRefDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RouteDefinition doParseRouteDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RouteDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "autoStartup": def.setAutoStartup(val); break;
+                case "delayer": def.setDelayer(val); break;
+                case "errorHandlerRef": def.setErrorHandlerRef(val); break;
+                case "group": def.setGroup(val); break;
+                case "logMask": def.setLogMask(val); break;
+                case "messageHistory": def.setMessageHistory(val); break;
+                case "routePolicyRef": def.setRoutePolicyRef(val); break;
+                case "shutdownRoute": def.setShutdownRoute(ShutdownRoute.valueOf(val)); break;
+                case "shutdownRunningTask": def.setShutdownRunningTask(ShutdownRunningTask.valueOf(val)); break;
+                case "startupOrder": def.setStartupOrder(Integer.valueOf(val)); break;
+                case "streamCache": def.setStreamCache(val); break;
+                case "trace": def.setTrace(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "from": def.setInput(doParseFromDefinition()); break;
+                case "inputType": def.setInputType(doParseInputTypeDefinition()); break;
+                case "outputType": def.setOutputType(doParseOutputTypeDefinition()); break;
+                case "routeProperty": doAdd(doParsePropertyDefinition(), def.getRouteProperties(), def::setRouteProperties); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RestDefinition doParseRestDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "apiDocs": def.setApiDocs(val); break;
+                case "bindingMode": def.setBindingMode(val); break;
+                case "clientRequestValidation": def.setClientRequestValidation(val); break;
+                case "consumes": def.setConsumes(val); break;
+                case "enableCORS": def.setEnableCORS(val); break;
+                case "path": def.setPath(val); break;
+                case "produces": def.setProduces(val); break;
+                case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+                case "tag": def.setTag(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "delete": doAdd(doParseDeleteVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "verb": doAdd(doParseVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "get": doAdd(doParseGetVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "head": doAdd(doParseHeadVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "patch": doAdd(doParsePatchVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "post": doAdd(doParsePostVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "put": doAdd(doParsePutVerbDefinition(), def.getVerbs(), def::setVerbs); break;
+                case "securityDefinitions": def.setSecurityDefinitions(doParseRestSecuritiesDefinition()); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RestBindingDefinition doParseRestBindingDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestBindingDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "bindingMode": def.setBindingMode(val); break;
+                case "clientRequestValidation": def.setClientRequestValidation(val); break;
+                case "component": def.setComponent(val); break;
+                case "consumes": def.setConsumes(val); break;
+                case "enableCORS": def.setEnableCORS(val); break;
+                case "outType": def.setOutType(val); break;
+                case "produces": def.setProduces(val); break;
+                case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+                case "type": def.setType(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    public RoutesDefinition parseRoutesDefinition()
+            throws IOException, XmlPullParserException {
+        expectTag("routes");
+        return doParseRoutesDefinition();
+    }
+    protected RoutesDefinition doParseRoutesDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RoutesDefinition(),
+            optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+            if ("route".equals(key)) {
+                doAdd(doParseRouteDefinition(), def.getRoutes(), def::setRoutes);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected RoutingSlipDefinition doParseRoutingSlipDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RoutingSlipDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "cacheSize": def.setCacheSize(val); break;
+                case "ignoreInvalidEndpoints": def.setIgnoreInvalidEndpoints(val); break;
+                case "uriDelimiter": def.setUriDelimiter(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SagaDefinition doParseSagaDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SagaDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "completionMode": def.setCompletionMode(SagaCompletionMode.valueOf(val)); break;
+                case "propagation": def.setPropagation(SagaPropagation.valueOf(val)); break;
+                case "sagaServiceRef": def.setSagaServiceRef(val); break;
+                case "timeoutInMilliseconds": def.setTimeoutInMilliseconds(Long.valueOf(val)); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "compensation": def.setCompensation(doParseSagaActionUriDefinition()); break;
+                case "completion": def.setCompletion(doParseSagaActionUriDefinition()); break;
+                case "option": doAdd(doParseSagaOptionDefinition(), def.getOptions(), def::setOptions); break;
+                default: return outputDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected SagaActionUriDefinition doParseSagaActionUriDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SagaActionUriDefinition(), (def, key, val) -> {
+            if ("uri".equals(key)) {
+                def.setUri(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected SagaOptionDefinition doParseSagaOptionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SagaOptionDefinition(), (def, key, val) -> {
+            if ("optionName".equals(key)) {
+                def.setOptionName(val);
+                return true;
+            }
+            return false;
+        }, (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpression(v);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected SamplingDefinition doParseSamplingDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SamplingDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "messageFrequency": def.setMessageFrequency(Long.valueOf(val)); break;
+                case "samplePeriod": def.setSamplePeriod(Long.valueOf(val)); break;
+                case "units": def.setUnits(TimeUnit.valueOf(val)); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ScriptDefinition doParseScriptDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ScriptDefinition(),
+            processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SetBodyDefinition doParseSetBodyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SetBodyDefinition(),
+            processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SetExchangePatternDefinition doParseSetExchangePatternDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SetExchangePatternDefinition(), (def, key, val) -> {
+            if ("pattern".equals(key)) {
+                def.setPattern(ExchangePattern.valueOf(val));
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected SetHeaderDefinition doParseSetHeaderDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SetHeaderDefinition(), (def, key, val) -> {
+            if ("name".equals(key)) {
+                def.setName(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SetPropertyDefinition doParseSetPropertyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SetPropertyDefinition(), (def, key, val) -> {
+            if ("name".equals(key)) {
+                def.setName(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SortDefinition doParseSortDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SortDefinition(), (def, key, val) -> {
+            if ("comparatorRef".equals(key)) {
+                def.setComparatorRef(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, expressionNodeElementHandler(), noValueHandler());
+    }
+    protected SplitDefinition doParseSplitDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SplitDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "onPrepareRef": def.setOnPrepareRef(val); break;
+                case "parallelAggregate": def.setParallelAggregate(Boolean.valueOf(val)); break;
+                case "parallelProcessing": def.setParallelProcessing(Boolean.valueOf(val)); break;
+                case "shareUnitOfWork": def.setShareUnitOfWork(Boolean.valueOf(val)); break;
+                case "stopOnAggregateException": def.setStopOnAggregateException(Boolean.valueOf(val)); break;
+                case "stopOnException": def.setStopOnException(Boolean.valueOf(val)); break;
+                case "strategyMethodAllowNull": def.setStrategyMethodAllowNull(Boolean.valueOf(val)); break;
+                case "strategyMethodName": def.setStrategyMethodName(val); break;
+                case "strategyRef": def.setStrategyRef(val); break;
+                case "streaming": def.setStreaming(Boolean.valueOf(val)); break;
+                case "timeout": def.setTimeout(Long.valueOf(val)); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected StepDefinition doParseStepDefinition() throws IOException, XmlPullParserException {
+        return doParse(new StepDefinition(),
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected StopDefinition doParseStopDefinition() throws IOException, XmlPullParserException {
+        return doParse(new StopDefinition(),
+            processorDefinitionAttributeHandler(), optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ThreadPoolProfileDefinition doParseThreadPoolProfileDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ThreadPoolProfileDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "allowCoreThreadTimeOut": def.setAllowCoreThreadTimeOut(val); break;
+                case "defaultProfile": def.setDefaultProfile(Boolean.valueOf(val)); break;
+                case "keepAliveTime": def.setKeepAliveTime(val); break;
+                case "maxPoolSize": def.setMaxPoolSize(val); break;
+                case "maxQueueSize": def.setMaxQueueSize(val); break;
+                case "poolSize": def.setPoolSize(val); break;
+                case "rejectedPolicy": def.setRejectedPolicy(val); break;
+                case "timeUnit": def.setTimeUnit(TimeUnit.valueOf(val)); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ThreadsDefinition doParseThreadsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ThreadsDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "allowCoreThreadTimeOut": def.setAllowCoreThreadTimeOut(val); break;
+                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "keepAliveTime": def.setKeepAliveTime(val); break;
+                case "maxPoolSize": def.setMaxPoolSize(val); break;
+                case "maxQueueSize": def.setMaxQueueSize(val); break;
+                case "poolSize": def.setPoolSize(val); break;
+                case "rejectedPolicy": def.setRejectedPolicy(ThreadPoolRejectedPolicy.valueOf(val)); break;
+                case "threadName": def.setThreadName(val); break;
+                case "timeUnit": def.setTimeUnit(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ThrottleDefinition doParseThrottleDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ThrottleDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "asyncDelayed": def.setAsyncDelayed(Boolean.valueOf(val)); break;
+                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(Boolean.valueOf(val)); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "rejectExecution": def.setRejectExecution(Boolean.valueOf(val)); break;
+                case "timePeriodMillis": def.setTimePeriodMillis(Long.valueOf(val)); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("correlationExpression".equals(key)) {
+                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+                return true;
+            }
+            return expressionNodeElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected ThrowExceptionDefinition doParseThrowExceptionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ThrowExceptionDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "exceptionType": def.setExceptionType(val); break;
+                case "message": def.setMessage(val); break;
+                case "ref": def.setRef(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected ToDefinition doParseToDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ToDefinition(), (def, key, val) -> {
+            if ("pattern".equals(key)) {
+                def.setPattern(val);
+                return true;
+            }
+            return sendDefinitionAttributeHandler().accept(def, key, val);
+        }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected <T extends ToDynamicDefinition> AttributeHandler<T> toDynamicDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "allowOptimisedComponents": def.setAllowOptimisedComponents(val); break;
+                case "cacheSize": def.setCacheSize(val); break;
+                case "ignoreInvalidEndpoint": def.setIgnoreInvalidEndpoint(val); break;
+                case "pattern": def.setPattern(val); break;
+                case "uri": def.setUri(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected ToDynamicDefinition doParseToDynamicDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ToDynamicDefinition(), toDynamicDefinitionAttributeHandler(),  optionalIdentifiedDefinitionElementHandler(), noValueHandler());
+    }
+    protected TransactedDefinition doParseTransactedDefinition() throws IOException, XmlPullParserException {
+        return doParse(new TransactedDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return processorDefinitionAttributeHandler().accept(def, key, val);
+        }, outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected TransformDefinition doParseTransformDefinition() throws IOException, XmlPullParserException {
+        return doParse(new TransformDefinition(),
+            processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+    }
+    protected TryDefinition doParseTryDefinition() throws IOException, XmlPullParserException {
+        return doParse(new TryDefinition(),
+            processorDefinitionAttributeHandler(), outputDefinitionElementHandler(), noValueHandler());
+    }
+    protected UnmarshalDefinition doParseUnmarshalDefinition() throws IOException, XmlPullParserException {
+        return doParse(new UnmarshalDefinition(),
+            processorDefinitionAttributeHandler(), (def, key) -> {
+            DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+            if (v != null) { 
+                def.setDataFormatType(v);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected ValidateDefinition doParseValidateDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ValidateDefinition(),
+            processorDefinitionAttributeHandler(), expressionNodeElementHandler(), noValueHandler());
+    }
+    protected WhenSkipSendToEndpointDefinition doParseWhenSkipSendToEndpointDefinition() throws IOException, XmlPullParserException {
+        return doParse(new WhenSkipSendToEndpointDefinition(),
+            processorDefinitionAttributeHandler(), outputExpressionNodeElementHandler(), noValueHandler());
+    }
+    protected WireTapDefinition doParseWireTapDefinition() throws IOException, XmlPullParserException {
+        return doParse(new WireTapDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "copy": def.setCopy(val); break;
+                case "dynamicUri": def.setDynamicUri(val); break;
+                case "executorServiceRef": def.setExecutorServiceRef(val); break;
+                case "onPrepareRef": def.setOnPrepareRef(val); break;
+                case "processorRef": def.setNewExchangeProcessorRef(val); break;
+                default: return toDynamicDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "setHeader": doAdd(doParseSetHeaderDefinition(), def.getHeaders(), def::setHeaders); break;
+                case "body": def.setNewExchangeExpression(doParseExpressionSubElementDefinition()); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected BlacklistServiceCallServiceFilterConfiguration doParseBlacklistServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new BlacklistServiceCallServiceFilterConfiguration(),
+            identifiedTypeAttributeHandler(), (def, key) -> {
+            if ("servers".equals(key)) {
+                doAdd(doParseText(), def.getServers(), def::setServers);
+                return true;
+            }
+            return serviceCallConfigurationElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected ServiceCallServiceFilterConfiguration doParseServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallServiceFilterConfiguration(), 
+            identifiedTypeAttributeHandler(),  serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected <T extends ServiceCallConfiguration> ElementHandler<T> serviceCallConfigurationElementHandler() {
+        return (def, key) -> {
+            if ("properties".equals(key)) {
+                doAdd(doParsePropertyDefinition(), def.getProperties(), def::setProperties);
+                return true;
+            }
+            return false;
+        };
+    }
+    protected CachingServiceCallServiceDiscoveryConfiguration doParseCachingServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new CachingServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "timeout": def.setTimeout(val); break;
+                case "units": def.setUnits(TimeUnit.valueOf(val)); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+                case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+                case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+                case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+                case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+                case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+                default: return serviceCallConfigurationElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ServiceCallServiceDiscoveryConfiguration doParseServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallServiceDiscoveryConfiguration(), 
+            identifiedTypeAttributeHandler(),  serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected CombinedServiceCallServiceDiscoveryConfiguration doParseCombinedServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new CombinedServiceCallServiceDiscoveryConfiguration(),
+            identifiedTypeAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "consulServiceDiscovery": doAdd(doParseConsulServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                case "dnsServiceDiscovery": doAdd(doParseDnsServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                case "etcdServiceDiscovery": doAdd(doParseEtcdServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                case "kubernetesServiceDiscovery": doAdd(doParseKubernetesServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                case "staticServiceDiscovery": doAdd(doParseStaticServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                case "cachingServiceDiscovery": doAdd(doParseCachingServiceCallServiceDiscoveryConfiguration(), def.getServiceDiscoveryConfigurations(), def::setServiceDiscoveryConfigurations); break;
+                default: return serviceCallConfigurationElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected CombinedServiceCallServiceFilterConfiguration doParseCombinedServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new CombinedServiceCallServiceFilterConfiguration(),
+            identifiedTypeAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "blacklistServiceFilter": doAdd(doParseBlacklistServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+                case "customServiceFilter": doAdd(doParseCustomServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+                case "healthyServiceFilter": doAdd(doParseHealthyServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+                case "passThroughServiceFilter": doAdd(doParsePassThroughServiceCallServiceFilterConfiguration(), def.getServiceFilterConfigurations(), def::setServiceFilterConfigurations); break;
+                default: return serviceCallConfigurationElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ConsulServiceCallServiceDiscoveryConfiguration doParseConsulServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ConsulServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "aclToken": def.setAclToken(val); break;
+                case "blockSeconds": def.setBlockSeconds(Integer.valueOf(val)); break;
+                case "connectTimeoutMillis": def.setConnectTimeoutMillis(Long.valueOf(val)); break;
+                case "datacenter": def.setDatacenter(val); break;
+                case "password": def.setPassword(val); break;
+                case "readTimeoutMillis": def.setReadTimeoutMillis(Long.valueOf(val)); break;
+                case "url": def.setUrl(val); break;
+                case "userName": def.setUserName(val); break;
+                case "writeTimeoutMillis": def.setWriteTimeoutMillis(Long.valueOf(val)); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected CustomServiceCallServiceFilterConfiguration doParseCustomServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new CustomServiceCallServiceFilterConfiguration(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setServiceFilterRef(val);
+                return true;
+            }
+            return identifiedTypeAttributeHandler().accept(def, key, val);
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected DefaultServiceCallServiceLoadBalancerConfiguration doParseDefaultServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new DefaultServiceCallServiceLoadBalancerConfiguration(),
+            identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected ServiceCallServiceLoadBalancerConfiguration doParseServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallServiceLoadBalancerConfiguration(), 
+            identifiedTypeAttributeHandler(),  serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected DnsServiceCallServiceDiscoveryConfiguration doParseDnsServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new DnsServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "domain": def.setDomain(val); break;
+                case "proto": def.setProto(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected EtcdServiceCallServiceDiscoveryConfiguration doParseEtcdServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new EtcdServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "password": def.setPassword(val); break;
+                case "servicePath": def.setServicePath(val); break;
+                case "timeout": def.setTimeout(Long.valueOf(val)); break;
+                case "type": def.setType(val); break;
+                case "uris": def.setUris(val); break;
+                case "userName": def.setUserName(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected HealthyServiceCallServiceFilterConfiguration doParseHealthyServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new HealthyServiceCallServiceFilterConfiguration(),
+            identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected KubernetesServiceCallServiceDiscoveryConfiguration doParseKubernetesServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new KubernetesServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "apiVersion": def.setApiVersion(val); break;
+                case "caCertData": def.setCaCertData(val); break;
+                case "caCertFile": def.setCaCertFile(val); break;
+                case "clientCertData": def.setClientCertData(val); break;
+                case "clientCertFile": def.setClientCertFile(val); break;
+                case "clientKeyAlgo": def.setClientKeyAlgo(val); break;
+                case "clientKeyData": def.setClientKeyData(val); break;
+                case "clientKeyFile": def.setClientKeyFile(val); break;
+                case "clientKeyPassphrase": def.setClientKeyPassphrase(val); break;
+                case "dnsDomain": def.setDnsDomain(val); break;
+                case "lookup": def.setLookup(val); break;
+                case "masterUrl": def.setMasterUrl(val); break;
+                case "namespace": def.setNamespace(val); break;
+                case "oauthToken": def.setOauthToken(val); break;
+                case "password": def.setPassword(val); break;
+                case "portName": def.setPortName(val); break;
+                case "portProtocol": def.setPortProtocol(val); break;
+                case "trustCerts": def.setTrustCerts(Boolean.valueOf(val)); break;
+                case "username": def.setUsername(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected PassThroughServiceCallServiceFilterConfiguration doParsePassThroughServiceCallServiceFilterConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new PassThroughServiceCallServiceFilterConfiguration(),
+            identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected RibbonServiceCallServiceLoadBalancerConfiguration doParseRibbonServiceCallServiceLoadBalancerConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new RibbonServiceCallServiceLoadBalancerConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "clientName": def.setClientName(val); break;
+                case "namespace": def.setNamespace(val); break;
+                case "password": def.setPassword(val); break;
+                case "username": def.setUsername(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected ServiceCallConfigurationDefinition doParseServiceCallConfigurationDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallConfigurationDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "component": def.setComponent(val); break;
+                case "expressionRef": def.setExpressionRef(val); break;
+                case "loadBalancerRef": def.setLoadBalancerRef(val); break;
+                case "pattern": def.setPattern(ExchangePattern.valueOf(val)); break;
+                case "serviceChooserRef": def.setServiceChooserRef(val); break;
+                case "serviceDiscoveryRef": def.setServiceDiscoveryRef(val); break;
+                case "serviceFilterRef": def.setServiceFilterRef(val); break;
+                case "uri": def.setUri(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "expression": def.setExpressionConfiguration(doParseServiceCallExpressionConfiguration()); break;
+                case "ribbonLoadBalancer": def.setLoadBalancerConfiguration(doParseRibbonServiceCallServiceLoadBalancerConfiguration()); break;
+                case "defaultLoadBalancer": def.setLoadBalancerConfiguration(doParseDefaultServiceCallServiceLoadBalancerConfiguration()); break;
+                case "cachingServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCachingServiceCallServiceDiscoveryConfiguration()); break;
+                case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+                case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+                case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+                case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+                case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+                case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+                case "zookeeperServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseZooKeeperServiceCallServiceDiscoveryConfiguration()); break;
+                case "blacklistServiceFilter": def.setServiceFilterConfiguration(doParseBlacklistServiceCallServiceFilterConfiguration()); break;
+                case "combinedServiceFilter": def.setServiceFilterConfiguration(doParseCombinedServiceCallServiceFilterConfiguration()); break;
+                case "customServiceFilter": def.setServiceFilterConfiguration(doParseCustomServiceCallServiceFilterConfiguration()); break;
+                case "healthyServiceFilter": def.setServiceFilterConfiguration(doParseHealthyServiceCallServiceFilterConfiguration()); break;
+                case "passThroughServiceFilter": def.setServiceFilterConfiguration(doParsePassThroughServiceCallServiceFilterConfiguration()); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ServiceCallExpressionConfiguration doParseServiceCallExpressionConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallExpressionConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "hostHeader": def.setHostHeader(val); break;
+                case "portHeader": def.setPortHeader(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpressionType(v);
+                return true;
+            }
+            return serviceCallConfigurationElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected ServiceCallDefinition doParseServiceCallDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "component": def.setComponent(val); break;
+                case "configurationRef": def.setConfigurationRef(val); break;
+                case "expressionRef": def.setExpressionRef(val); break;
+                case "loadBalancerRef": def.setLoadBalancerRef(val); break;
+                case "name": def.setName(val); break;
+                case "pattern": def.setPattern(ExchangePattern.valueOf(val)); break;
+                case "serviceChooserRef": def.setServiceChooserRef(val); break;
+                case "serviceDiscoveryRef": def.setServiceDiscoveryRef(val); break;
+                case "serviceFilterRef": def.setServiceFilterRef(val); break;
+                case "uri": def.setUri(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "expressionConfiguration": def.setExpressionConfiguration(doParseServiceCallExpressionConfiguration()); break;
+                case "ribbonLoadBalancer": def.setLoadBalancerConfiguration(doParseRibbonServiceCallServiceLoadBalancerConfiguration()); break;
+                case "defaultLoadBalancer": def.setLoadBalancerConfiguration(doParseDefaultServiceCallServiceLoadBalancerConfiguration()); break;
+                case "cachingServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCachingServiceCallServiceDiscoveryConfiguration()); break;
+                case "combinedServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseCombinedServiceCallServiceDiscoveryConfiguration()); break;
+                case "consulServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseConsulServiceCallServiceDiscoveryConfiguration()); break;
+                case "dnsServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseDnsServiceCallServiceDiscoveryConfiguration()); break;
+                case "etcdServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseEtcdServiceCallServiceDiscoveryConfiguration()); break;
+                case "kubernetesServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseKubernetesServiceCallServiceDiscoveryConfiguration()); break;
+                case "staticServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseStaticServiceCallServiceDiscoveryConfiguration()); break;
+                case "zookeeperServiceDiscovery": def.setServiceDiscoveryConfiguration(doParseZooKeeperServiceCallServiceDiscoveryConfiguration()); break;
+                case "blacklistServiceFilter": def.setServiceFilterConfiguration(doParseBlacklistServiceCallServiceFilterConfiguration()); break;
+                case "combinedServiceFilter": def.setServiceFilterConfiguration(doParseCombinedServiceCallServiceFilterConfiguration()); break;
+                case "customServiceFilter": def.setServiceFilterConfiguration(doParseCustomServiceCallServiceFilterConfiguration()); break;
+                case "healthyServiceFilter": def.setServiceFilterConfiguration(doParseHealthyServiceCallServiceFilterConfiguration()); break;
+                case "passThroughServiceFilter": def.setServiceFilterConfiguration(doParsePassThroughServiceCallServiceFilterConfiguration()); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ServiceCallServiceChooserConfiguration doParseServiceCallServiceChooserConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ServiceCallServiceChooserConfiguration(),
+            identifiedTypeAttributeHandler(), serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected StaticServiceCallServiceDiscoveryConfiguration doParseStaticServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new StaticServiceCallServiceDiscoveryConfiguration(),
+            identifiedTypeAttributeHandler(), (def, key) -> {
+            if ("servers".equals(key)) {
+                doAdd(doParseText(), def.getServers(), def::setServers);
+                return true;
+            }
+            return serviceCallConfigurationElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected ZooKeeperServiceCallServiceDiscoveryConfiguration doParseZooKeeperServiceCallServiceDiscoveryConfiguration() throws IOException, XmlPullParserException {
+        return doParse(new ZooKeeperServiceCallServiceDiscoveryConfiguration(), (def, key, val) -> {
+            switch (key) {
+                case "basePath": def.setBasePath(val); break;
+                case "connectionTimeout": def.setConnectionTimeout(val); break;
+                case "namespace": def.setNamespace(val); break;
+                case "nodes": def.setNodes(val); break;
+                case "reconnectBaseSleepTime": def.setReconnectBaseSleepTime(val); break;
+                case "reconnectMaxRetries": def.setReconnectMaxRetries(val); break;
+                case "reconnectMaxSleepTime": def.setReconnectMaxSleepTime(val); break;
+                case "sessionTimeout": def.setSessionTimeout(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, serviceCallConfigurationElementHandler(), noValueHandler());
+    }
+    protected BatchResequencerConfig doParseBatchResequencerConfig() throws IOException, XmlPullParserException {
+        return doParse(new BatchResequencerConfig(), (def, key, val) -> {
+            switch (key) {
+                case "allowDuplicates": def.setAllowDuplicates(val); break;
+                case "batchSize": def.setBatchSize(val); break;
+                case "batchTimeout": def.setBatchTimeout(val); break;
+                case "ignoreInvalidExchanges": def.setIgnoreInvalidExchanges(val); break;
+                case "reverse": def.setReverse(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected StreamResequencerConfig doParseStreamResequencerConfig() throws IOException, XmlPullParserException {
+        return doParse(new StreamResequencerConfig(), (def, key, val) -> {
+            switch (key) {
+                case "capacity": def.setCapacity(val); break;
+                case "comparatorRef": def.setComparatorRef(val); break;
+                case "deliveryAttemptInterval": def.setDeliveryAttemptInterval(val); break;
+                case "ignoreInvalidExchanges": def.setIgnoreInvalidExchanges(val); break;
+                case "rejectOld": def.setRejectOld(val); break;
+                case "timeout": def.setTimeout(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ASN1DataFormat doParseASN1DataFormat() throws IOException, XmlPullParserException {
+        return doParse(new ASN1DataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "clazzName": def.setClazzName(val); break;
+                case "usingIterator": def.setUsingIterator(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected Any23DataFormat doParseAny23DataFormat() throws IOException, XmlPullParserException {
+        return doParse(new Any23DataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "baseURI": def.setBaseURI(val); break;
+                case "outputFormat": def.setOutputFormat(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "configuration": def.setConfiguration(unmarshal(new PropertyDescriptionsAdapter(), doParsePropertyDefinitions())); break;
+                case "extractors": doAdd(doParseText(), def.getExtractors(), def::setExtractors); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected AvroDataFormat doParseAvroDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new AvroDataFormat(), (def, key, val) -> {
+            if ("instanceClassName".equals(key)) {
+                def.setInstanceClassName(val);
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected BarcodeDataFormat doParseBarcodeDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new BarcodeDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "barcodeFormat": def.setBarcodeFormat(val); break;
+                case "height": def.setHeight(val); break;
+                case "imageType": def.setImageType(val); break;
+                case "width": def.setWidth(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected Base64DataFormat doParseBase64DataFormat() throws IOException, XmlPullParserException {
+        return doParse(new Base64DataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "lineLength": def.setLineLength(val); break;
+                case "lineSeparator": def.setLineSeparator(val); break;
+                case "urlSafe": def.setUrlSafe(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected BeanioDataFormat doParseBeanioDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new BeanioDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "beanReaderErrorHandlerType": def.setBeanReaderErrorHandlerType(val); break;
+                case "encoding": def.setEncoding(val); break;
+                case "ignoreInvalidRecords": def.setIgnoreInvalidRecords(val); break;
+                case "ignoreUnexpectedRecords": def.setIgnoreUnexpectedRecords(val); break;
+                case "ignoreUnidentifiedRecords": def.setIgnoreUnidentifiedRecords(val); break;
+                case "mapping": def.setMapping(val); break;
+                case "streamName": def.setStreamName(val); break;
+                case "unmarshalSingleObject": def.setUnmarshalSingleObject(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected BindyDataFormat doParseBindyDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new BindyDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowEmptyStream": def.setAllowEmptyStream(Boolean.valueOf(val)); break;
+                case "classType": def.setClassType(val); break;
+                case "locale": def.setLocale(val); break;
+                case "type": def.setType(BindyType.valueOf(val)); break;
+                case "unwrapSingleInstance": def.setUnwrapSingleInstance(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected CBORDataFormat doParseCBORDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new CBORDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowJmsType": def.setAllowJmsType(val); break;
+                case "allowUnmarshallType": def.setAllowUnmarshallType(val); break;
+                case "collectionTypeName": def.setCollectionTypeName(val); break;
+                case "disableFeatures": def.setDisableFeatures(val); break;
+                case "enableFeatures": def.setEnableFeatures(val); break;
+                case "objectMapper": def.setObjectMapper(val); break;
+                case "prettyPrint": def.setPrettyPrint(val); break;
+                case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+                case "useDefaultObjectMapper": def.setUseDefaultObjectMapper(val); break;
+                case "useList": def.setUseList(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected CryptoDataFormat doParseCryptoDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new CryptoDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "algorithm": def.setAlgorithm(val); break;
+                case "algorithmParameterRef": def.setAlgorithmParameterRef(val); break;
+                case "buffersize": def.setBuffersize(val); break;
+                case "cryptoProvider": def.setCryptoProvider(val); break;
+                case "initVectorRef": def.setInitVectorRef(val); break;
+                case "inline": def.setInline(val); break;
+                case "keyRef": def.setKeyRef(val); break;
+                case "macAlgorithm": def.setMacAlgorithm(val); break;
+                case "shouldAppendHMAC": def.setShouldAppendHMAC(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected CsvDataFormat doParseCsvDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new CsvDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowMissingColumnNames": def.setAllowMissingColumnNames(Boolean.valueOf(val)); break;
+                case "commentMarker": def.setCommentMarker(val); break;
+                case "commentMarkerDisabled": def.setCommentMarkerDisabled(Boolean.valueOf(val)); break;
+                case "delimiter": def.setDelimiter(val); break;
+                case "escape": def.setEscape(val); break;
+                case "escapeDisabled": def.setEscapeDisabled(Boolean.valueOf(val)); break;
+                case "formatName": def.setFormatName(val); break;
+                case "formatRef": def.setFormatRef(val); break;
+                case "headerDisabled": def.setHeaderDisabled(Boolean.valueOf(val)); break;
+                case "ignoreEmptyLines": def.setIgnoreEmptyLines(Boolean.valueOf(val)); break;
+                case "ignoreHeaderCase": def.setIgnoreHeaderCase(Boolean.valueOf(val)); break;
+                case "ignoreSurroundingSpaces": def.setIgnoreSurroundingSpaces(Boolean.valueOf(val)); break;
+                case "lazyLoad": def.setLazyLoad(Boolean.valueOf(val)); break;
+                case "marshallerFactoryRef": def.setMarshallerFactoryRef(val); break;
+                case "nullString": def.setNullString(val); break;
+                case "nullStringDisabled": def.setNullStringDisabled(Boolean.valueOf(val)); break;
+                case "quote": def.setQuote(val); break;
+                case "quoteDisabled": def.setQuoteDisabled(Boolean.valueOf(val)); break;
+                case "quoteMode": def.setQuoteMode(val); break;
+                case "recordConverterRef": def.setRecordConverterRef(val); break;
+                case "recordSeparator": def.setRecordSeparator(val); break;
+                case "recordSeparatorDisabled": def.setRecordSeparatorDisabled(val); break;
+                case "skipHeaderRecord": def.setSkipHeaderRecord(Boolean.valueOf(val)); break;
+                case "trailingDelimiter": def.setTrailingDelimiter(Boolean.valueOf(val)); break;
+                case "trim": def.setTrim(Boolean.valueOf(val)); break;
+                case "useMaps": def.setUseMaps(Boolean.valueOf(val)); break;
+                case "useOrderedMaps": def.setUseOrderedMaps(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("header".equals(key)) {
+                doAdd(doParseText(), def.getHeader(), def::setHeader);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected CustomDataFormat doParseCustomDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new CustomDataFormat(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected DataFormatsDefinition doParseDataFormatsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DataFormatsDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+            if (v != null) { 
+                doAdd(v, def.getDataFormats(), def::setDataFormats);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected FhirJsonDataFormat doParseFhirJsonDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new FhirJsonDataFormat(),
+            fhirDataformatAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected <T extends FhirDataformat> AttributeHandler<T> fhirDataformatAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "dontEncodeElements": def.setDontEncodeElements(asStringSet(val)); break;
+                case "dontStripVersionsFromReferencesAtPaths": def.setDontStripVersionsFromReferencesAtPaths(asStringList(val)); break;
+                case "encodeElements": def.setEncodeElements(asStringSet(val)); break;
+                case "encodeElementsAppliesToChildResourcesOnly": def.setEncodeElementsAppliesToChildResourcesOnly(Boolean.valueOf(val)); break;
+                case "fhirVersion": def.setFhirVersion(val); break;
+                case "omitResourceId": def.setOmitResourceId(Boolean.valueOf(val)); break;
+                case "overrideResourceIdWithBundleEntryFullUrl": def.setOverrideResourceIdWithBundleEntryFullUrl(Boolean.valueOf(val)); break;
+                case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+                case "serverBaseUrl": def.setServerBaseUrl(val); break;
+                case "stripVersionsFromReferences": def.setStripVersionsFromReferences(Boolean.valueOf(val)); break;
+                case "summaryMode": def.setSummaryMode(Boolean.valueOf(val)); break;
+                case "suppressNarratives": def.setSuppressNarratives(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected FhirXmlDataFormat doParseFhirXmlDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new FhirXmlDataFormat(),
+            fhirDataformatAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected FlatpackDataFormat doParseFlatpackDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new FlatpackDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowShortLines": def.setAllowShortLines(Boolean.valueOf(val)); break;
+                case "definition": def.setDefinition(val); break;
+                case "delimiter": def.setDelimiter(val); break;
+                case "fixed": def.setFixed(Boolean.valueOf(val)); break;
+                case "ignoreExtraColumns": def.setIgnoreExtraColumns(Boolean.valueOf(val)); break;
+                case "ignoreFirstRecord": def.setIgnoreFirstRecord(Boolean.valueOf(val)); break;
+                case "parserFactoryRef": def.setParserFactoryRef(val); break;
+                case "textQualifier": def.setTextQualifier(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected GrokDataFormat doParseGrokDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new GrokDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowMultipleMatchesPerLine": def.setAllowMultipleMatchesPerLine(Boolean.valueOf(val)); break;
+                case "flattened": def.setFlattened(Boolean.valueOf(val)); break;
+                case "namedOnly": def.setNamedOnly(Boolean.valueOf(val)); break;
+                case "pattern": def.setPattern(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected GzipDataFormat doParseGzipDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new GzipDataFormat(),
+            dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected HL7DataFormat doParseHL7DataFormat() throws IOException, XmlPullParserException {
+        return doParse(new HL7DataFormat(), (def, key, val) -> {
+            if ("validate".equals(key)) {
+                def.setValidate(Boolean.valueOf(val));
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected IcalDataFormat doParseIcalDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new IcalDataFormat(), (def, key, val) -> {
+            if ("validating".equals(key)) {
+                def.setValidating(Boolean.valueOf(val));
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected JacksonXMLDataFormat doParseJacksonXMLDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new JacksonXMLDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowJmsType": def.setAllowJmsType(val); break;
+                case "allowUnmarshallType": def.setAllowUnmarshallType(val); break;
+                case "collectionTypeName": def.setCollectionTypeName(val); break;
+                case "disableFeatures": def.setDisableFeatures(val); break;
+                case "enableFeatures": def.setEnableFeatures(val); break;
+                case "enableJaxbAnnotationModule": def.setEnableJaxbAnnotationModule(val); break;
+                case "include": def.setInclude(val); break;
+                case "jsonView": def.setJsonView(asClass(val)); break;
+                case "moduleClassNames": def.setModuleClassNames(val); break;
+                case "moduleRefs": def.setModuleRefs(val); break;
+                case "prettyPrint": def.setPrettyPrint(val); break;
+                case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+                case "useList": def.setUseList(val); break;
+                case "xmlMapper": def.setXmlMapper(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected JaxbDataFormat doParseJaxbDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new JaxbDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "contextPath": def.setContextPath(val); break;
+                case "encoding": def.setEncoding(val); break;
+                case "filterNonXmlChars": def.setFilterNonXmlChars(Boolean.valueOf(val)); break;
+                case "fragment": def.setFragment(Boolean.valueOf(val)); break;
+                case "ignoreJAXBElement": def.setIgnoreJAXBElement(Boolean.valueOf(val)); break;
+                case "jaxbProviderProperties": def.setJaxbProviderProperties(val); break;
+                case "mustBeJAXBElement": def.setMustBeJAXBElement(Boolean.valueOf(val)); break;
+                case "namespacePrefixRef": def.setNamespacePrefixRef(val); break;
+                case "noNamespaceSchemaLocation": def.setNoNamespaceSchemaLocation(val); break;
+                case "objectFactory": def.setObjectFactory(Boolean.valueOf(val)); break;
+                case "partClass": def.setPartClass(val); break;
+                case "partNamespace": def.setPartNamespace(val); break;
+                case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+                case "schema": def.setSchema(val); break;
+                case "schemaLocation": def.setSchemaLocation(val); break;
+                case "schemaSeverityLevel": def.setSchemaSeverityLevel(Integer.valueOf(val)); break;
+                case "xmlStreamWriterWrapper": def.setXmlStreamWriterWrapper(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected JsonApiDataFormat doParseJsonApiDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new JsonApiDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "dataFormatTypes": def.setDataFormatTypes(asClassArray(val)); break;
+                case "mainFormatType": def.setMainFormatType(asClass(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected JsonDataFormat doParseJsonDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new JsonDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowJmsType": def.setAllowJmsType(Boolean.valueOf(val)); break;
+                case "allowUnmarshallType": def.setAllowUnmarshallType(Boolean.valueOf(val)); break;
+                case "autoDiscoverObjectMapper": def.setAutoDiscoverObjectMapper(Boolean.valueOf(val)); break;
+                case "collectionTypeName": def.setCollectionTypeName(val); break;
+                case "disableFeatures": def.setDisableFeatures(val); break;
+                case "enableFeatures": def.setEnableFeatures(val); break;
+                case "enableJaxbAnnotationModule": def.setEnableJaxbAnnotationModule(Boolean.valueOf(val)); break;
+                case "include": def.setInclude(val); break;
+                case "jsonView": def.setJsonView(asClass(val)); break;
+                case "library": def.setLibrary(JsonLibrary.valueOf(val)); break;
+                case "moduleClassNames": def.setModuleClassNames(val); break;
+                case "moduleRefs": def.setModuleRefs(val); break;
+                case "objectMapper": def.setObjectMapper(val); break;
+                case "permissions": def.setPermissions(val); break;
+                case "prettyPrint": def.setPrettyPrint(Boolean.valueOf(val)); break;
+                case "timezone": def.setTimezone(val); break;
+                case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+                case "useDefaultObjectMapper": def.setUseDefaultObjectMapper(Boolean.valueOf(val)); break;
+                case "useList": def.setUseList(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected LZFDataFormat doParseLZFDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new LZFDataFormat(), (def, key, val) -> {
+            if ("usingParallelCompression".equals(key)) {
+                def.setUsingParallelCompression(Boolean.valueOf(val));
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected MimeMultipartDataFormat doParseMimeMultipartDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new MimeMultipartDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "binaryContent": def.setBinaryContent(Boolean.valueOf(val)); break;
+                case "headersInline": def.setHeadersInline(Boolean.valueOf(val)); break;
+                case "includeHeaders": def.setIncludeHeaders(val); break;
+                case "multipartSubType": def.setMultipartSubType(val); break;
+                case "multipartWithoutAttachment": def.setMultipartWithoutAttachment(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected PGPDataFormat doParsePGPDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new PGPDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "algorithm": def.setAlgorithm(val); break;
+                case "armored": def.setArmored(val); break;
+                case "compressionAlgorithm": def.setCompressionAlgorithm(val); break;
+                case "hashAlgorithm": def.setHashAlgorithm(val); break;
+                case "integrity": def.setIntegrity(val); break;
+                case "keyFileName": def.setKeyFileName(val); break;
+                case "keyUserid": def.setKeyUserid(val); break;
+                case "password": def.setPassword(val); break;
+                case "provider": def.setProvider(val); break;
+                case "signatureKeyFileName": def.setSignatureKeyFileName(val); break;
+                case "signatureKeyRing": def.setSignatureKeyRing(val); break;
+                case "signatureKeyUserid": def.setSignatureKeyUserid(val); break;
+                case "signaturePassword": def.setSignaturePassword(val); break;
+                case "signatureVerificationOption": def.setSignatureVerificationOption(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ProtobufDataFormat doParseProtobufDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new ProtobufDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "contentTypeFormat": def.setContentTypeFormat(val); break;
+                case "instanceClass": def.setInstanceClass(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RssDataFormat doParseRssDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new RssDataFormat(),
+            dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected SoapJaxbDataFormat doParseSoapJaxbDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new SoapJaxbDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "contextPath": def.setContextPath(val); break;
+                case "elementNameStrategyRef": def.setElementNameStrategyRef(val); break;
+                case "encoding": def.setEncoding(val); break;
+                case "namespacePrefixRef": def.setNamespacePrefixRef(val); break;
+                case "schema": def.setSchema(val); break;
+                case "version": def.setVersion(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected SyslogDataFormat doParseSyslogDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new SyslogDataFormat(),
+            dataFormatDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected TarFileDataFormat doParseTarFileDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new TarFileDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowEmptyDirectory": def.setAllowEmptyDirectory(Boolean.valueOf(val)); break;
+                case "preservePathElements": def.setPreservePathElements(Boolean.valueOf(val)); break;
+                case "usingIterator": def.setUsingIterator(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ThriftDataFormat doParseThriftDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new ThriftDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "contentTypeFormat": def.setContentTypeFormat(val); break;
+                case "instanceClass": def.setInstanceClass(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected TidyMarkupDataFormat doParseTidyMarkupDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new TidyMarkupDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "dataObjectType": def.setDataObjectTypeName(val); break;
+                case "omitXmlDeclaration": def.setOmitXmlDeclaration(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected UniVocityCsvDataFormat doParseUniVocityCsvDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new UniVocityCsvDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "delimiter": def.setDelimiter(val); break;
+                case "quote": def.setQuote(val); break;
+                case "quoteAllFields": def.setQuoteAllFields(Boolean.valueOf(val)); break;
+                case "quoteEscape": def.setQuoteEscape(val); break;
+                default: return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+    }
+    protected <T extends UniVocityAbstractDataFormat> AttributeHandler<T> uniVocityAbstractDataFormatAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "asMap": def.setAsMap(Boolean.valueOf(val)); break;
+                case "comment": def.setComment(val); break;
+                case "emptyValue": def.setEmptyValue(val); break;
+                case "headerExtractionEnabled": def.setHeaderExtractionEnabled(Boolean.valueOf(val)); break;
+                case "headersDisabled": def.setHeadersDisabled(Boolean.valueOf(val)); break;
+                case "ignoreLeadingWhitespaces": def.setIgnoreLeadingWhitespaces(Boolean.valueOf(val)); break;
+                case "ignoreTrailingWhitespaces": def.setIgnoreTrailingWhitespaces(Boolean.valueOf(val)); break;
+                case "lazyLoad": def.setLazyLoad(Boolean.valueOf(val)); break;
+                case "lineSeparator": def.setLineSeparator(val); break;
+                case "normalizedLineSeparator": def.setNormalizedLineSeparator(val); break;
+                case "nullValue": def.setNullValue(val); break;
+                case "numberOfRecordsToRead": def.setNumberOfRecordsToRead(Integer.valueOf(val)); break;
+                case "skipEmptyLines": def.setSkipEmptyLines(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected <T extends UniVocityAbstractDataFormat> ElementHandler<T> uniVocityAbstractDataFormatElementHandler() {
+        return (def, key) -> {
+            if ("univocity-header".equals(key)) {
+                doAdd(doParseUniVocityHeader(), def.getHeaders(), def::setHeaders);
+                return true;
+            }
+            return false;
+        };
+    }
+    protected UniVocityHeader doParseUniVocityHeader() throws IOException, XmlPullParserException {
+        return doParse(new UniVocityHeader(), (def, key, val) -> {
+            if ("length".equals(key)) {
+                def.setLength(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), (def, val) -> def.setName(val));
+    }
+    protected UniVocityFixedWidthDataFormat doParseUniVocityFixedWidthDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new UniVocityFixedWidthDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "padding": def.setPadding(val); break;
+                case "recordEndsOnNewline": def.setRecordEndsOnNewline(Boolean.valueOf(val)); break;
+                case "skipTrailingCharsUntilNewline": def.setSkipTrailingCharsUntilNewline(Boolean.valueOf(val)); break;
+                default: return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+    }
+    protected UniVocityTsvDataFormat doParseUniVocityTsvDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new UniVocityTsvDataFormat(), (def, key, val) -> {
+            if ("escapeChar".equals(key)) {
+                def.setEscapeChar(val);
+                return true;
+            }
+            return uniVocityAbstractDataFormatAttributeHandler().accept(def, key, val);
+        }, uniVocityAbstractDataFormatElementHandler(), noValueHandler());
+    }
+    protected XMLSecurityDataFormat doParseXMLSecurityDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new XMLSecurityDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "addKeyValueForEncryptedKey": def.setAddKeyValueForEncryptedKey(Boolean.valueOf(val)); break;
+                case "digestAlgorithm": def.setDigestAlgorithm(val); break;
+                case "keyCipherAlgorithm": def.setKeyCipherAlgorithm(val); break;
+                case "keyOrTrustStoreParametersRef": def.setKeyOrTrustStoreParametersRef(val); break;
+                case "keyPassword": def.setKeyPassword(val); break;
+                case "mgfAlgorithm": def.setMgfAlgorithm(val); break;
+                case "passPhrase": def.setPassPhrase(val); break;
+                case "passPhraseByte": def.setPassPhraseByte(asByteArray(val)); break;
+                case "recipientKeyAlias": def.setRecipientKeyAlias(val); break;
+                case "secureTag": def.setSecureTag(val); break;
+                case "secureTagContents": def.setSecureTagContents(Boolean.valueOf(val)); break;
+                case "xmlCipherAlgorithm": def.setXmlCipherAlgorithm(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected XStreamDataFormat doParseXStreamDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "driver": def.setDriver(val); break;
+                case "driverRef": def.setDriverRef(val); break;
+                case "encoding": def.setEncoding(val); break;
+                case "mode": def.setMode(val); break;
+                case "permissions": def.setPermissions(val); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "aliases": def.setAliases(unmarshal(new XStreamDataFormat.AliasAdapter(), doParseAliasList())); break;
+                case "converters": def.setConverters(unmarshal(new XStreamDataFormat.ConvertersAdapter(), doParseConverterList())); break;
+                case "implicitCollections": def.setImplicitCollections(unmarshal(new XStreamDataFormat.ImplicitCollectionsAdapter(), doParseImplicitCollectionList())); break;
+                case "omitFields": def.setOmitFields(unmarshal(new XStreamDataFormat.OmitFieldsAdapter(), doParseOmitFieldList())); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.ConverterList doParseConverterList() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.ConverterList(),
+            noAttributeHandler(), (def, key) -> {
+            if ("converter".equals(key)) {
+                doAdd(doParseConverterEntry(), def.getList(), def::setList);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.AliasList doParseAliasList() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.AliasList(),
+            noAttributeHandler(), (def, key) -> {
+            if ("alias".equals(key)) {
+                doAdd(doParseAliasEntry(), def.getList(), def::setList);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.OmitFieldList doParseOmitFieldList() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.OmitFieldList(),
+            noAttributeHandler(), (def, key) -> {
+            if ("omitField".equals(key)) {
+                doAdd(doParseOmitFieldEntry(), def.getList(), def::setList);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.ImplicitCollectionList doParseImplicitCollectionList() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.ImplicitCollectionList(),
+            noAttributeHandler(), (def, key) -> {
+            if ("class".equals(key)) {
+                doAdd(doParseImplicitCollectionEntry(), def.getList(), def::setList);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.AliasEntry doParseAliasEntry() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.AliasEntry(), (def, key, val) -> {
+            switch (key) {
+                case "class": def.setClsName(val); break;
+                case "name": def.setName(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected XStreamDataFormat.ConverterEntry doParseConverterEntry() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.ConverterEntry(), (def, key, val) -> {
+            if ("class".equals(key)) {
+                def.setClsName(val);
+                return true;
+            }
+            return false;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected XStreamDataFormat.ImplicitCollectionEntry doParseImplicitCollectionEntry() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.ImplicitCollectionEntry(), (def, key, val) -> {
+            if ("name".equals(key)) {
+                def.setClsName(val);
+                return true;
+            }
+            return false;
+        }, (def, key) -> {
+            if ("field".equals(key)) {
+                doAdd(doParseText(), def.getFields(), def::setFields);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XStreamDataFormat.OmitFieldEntry doParseOmitFieldEntry() throws IOException, XmlPullParserException {
+        return doParse(new XStreamDataFormat.OmitFieldEntry(), (def, key, val) -> {
+            if ("class".equals(key)) {
+                def.setClsName(val);
+                return true;
+            }
+            return false;
+        }, (def, key) -> {
+            if ("field".equals(key)) {
+                doAdd(doParseText(), def.getFields(), def::setFields);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected XmlRpcDataFormat doParseXmlRpcDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new XmlRpcDataFormat(), (def, key, val) -> {
+            if ("request".equals(key)) {
+                def.setRequest(Boolean.valueOf(val));
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected YAMLDataFormat doParseYAMLDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new YAMLDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowAnyType": def.setAllowAnyType(Boolean.valueOf(val)); break;
+                case "constructor": def.setConstructor(val); break;
+                case "dumperOptions": def.setDumperOptions(val); break;
+                case "library": def.setLibrary(YAMLLibrary.valueOf(val)); break;
+                case "prettyFlow": def.setPrettyFlow(Boolean.valueOf(val)); break;
+                case "representer": def.setRepresenter(val); break;
+                case "resolver": def.setResolver(val); break;
+                case "unmarshalTypeName": def.setUnmarshalTypeName(val); break;
+                case "useApplicationContextClassLoader": def.setUseApplicationContextClassLoader(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("typeFilter".equals(key)) {
+                doAdd(doParseYAMLTypeFilterDefinition(), def.getTypeFilters(), def::setTypeFilters);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected YAMLTypeFilterDefinition doParseYAMLTypeFilterDefinition() throws IOException, XmlPullParserException {
+        return doParse(new YAMLTypeFilterDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "type": def.setType(YAMLTypeFilterType.valueOf(val)); break;
+                case "value": def.setValue(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ZipDeflaterDataFormat doParseZipDeflaterDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new ZipDeflaterDataFormat(), (def, key, val) -> {
+            if ("compressionLevel".equals(key)) {
+                def.setCompressionLevel(Integer.valueOf(val));
+                return true;
+            }
+            return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ZipFileDataFormat doParseZipFileDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new ZipFileDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "allowEmptyDirectory": def.setAllowEmptyDirectory(Boolean.valueOf(val)); break;
+                case "preservePathElements": def.setPreservePathElements(Boolean.valueOf(val)); break;
+                case "usingIterator": def.setUsingIterator(Boolean.valueOf(val)); break;
+                default: return dataFormatDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected ConstantExpression doParseConstantExpression() throws IOException, XmlPullParserException {
+        return doParse(new ConstantExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected ExchangePropertyExpression doParseExchangePropertyExpression() throws IOException, XmlPullParserException {
+        return doParse(new ExchangePropertyExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected GroovyExpression doParseGroovyExpression() throws IOException, XmlPullParserException {
+        return doParse(new GroovyExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected HeaderExpression doParseHeaderExpression() throws IOException, XmlPullParserException {
+        return doParse(new HeaderExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected Hl7TerserExpression doParseHl7TerserExpression() throws IOException, XmlPullParserException {
+        return doParse(new Hl7TerserExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected JsonPathExpression doParseJsonPathExpression() throws IOException, XmlPullParserException {
+        return doParse(new JsonPathExpression(), (def, key, val) -> {
+            switch (key) {
+                case "allowEasyPredicate": def.setAllowEasyPredicate(val); break;
+                case "allowSimple": def.setAllowSimple(val); break;
+                case "headerName": def.setHeaderName(val); break;
+                case "resultType": def.setResultTypeName(val); break;
+                case "suppressExceptions": def.setSuppressExceptions(val); break;
+                case "writeAsString": def.setWriteAsString(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected LanguageExpression doParseLanguageExpression() throws IOException, XmlPullParserException {
+        return doParse(new LanguageExpression(), (def, key, val) -> {
+            if ("language".equals(key)) {
+                def.setLanguage(val);
+                return true;
+            }
+            return expressionDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected MethodCallExpression doParseMethodCallExpression() throws IOException, XmlPullParserException {
+        return doParse(new MethodCallExpression(), (def, key, val) -> {
+            switch (key) {
+                case "beanType": def.setBeanTypeName(val); break;
+                case "method": def.setMethod(val); break;
+                case "ref": def.setRef(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected MvelExpression doParseMvelExpression() throws IOException, XmlPullParserException {
+        return doParse(new MvelExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected OgnlExpression doParseOgnlExpression() throws IOException, XmlPullParserException {
+        return doParse(new OgnlExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected RefExpression doParseRefExpression() throws IOException, XmlPullParserException {
+        return doParse(new RefExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected SimpleExpression doParseSimpleExpression() throws IOException, XmlPullParserException {
+        return doParse(new SimpleExpression(), (def, key, val) -> {
+            if ("resultType".equals(key)) {
+                def.setResultTypeName(val);
+                return true;
+            }
+            return expressionDefinitionAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected SpELExpression doParseSpELExpression() throws IOException, XmlPullParserException {
+        return doParse(new SpELExpression(),
+            expressionDefinitionAttributeHandler(), noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected TokenizerExpression doParseTokenizerExpression() throws IOException, XmlPullParserException {
+        return doParse(new TokenizerExpression(), (def, key, val) -> {
+            switch (key) {
+                case "endToken": def.setEndToken(val); break;
+                case "group": def.setGroup(val); break;
+                case "groupDelimiter": def.setGroupDelimiter(val); break;
+                case "headerName": def.setHeaderName(val); break;
+                case "includeTokens": def.setIncludeTokens(val); break;
+                case "inheritNamespaceTagName": def.setInheritNamespaceTagName(val); break;
+                case "regex": def.setRegex(val); break;
+                case "skipFirst": def.setSkipFirst(val); break;
+                case "token": def.setToken(val); break;
+                case "xml": def.setXml(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected XMLTokenizerExpression doParseXMLTokenizerExpression() throws IOException, XmlPullParserException {
+        return doParse(new XMLTokenizerExpression(), (def, key, val) -> {
+            switch (key) {
+                case "group": def.setGroup(val); break;
+                case "headerName": def.setHeaderName(val); break;
+                case "mode": def.setMode(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected XPathExpression doParseXPathExpression() throws IOException, XmlPullParserException {
+        return doParse(new XPathExpression(), (def, key, val) -> {
+            switch (key) {
+                case "documentType": def.setDocumentTypeName(val); break;
+                case "factoryRef": def.setFactoryRef(val); break;
+                case "headerName": def.setHeaderName(val); break;
+                case "logNamespaces": def.setLogNamespaces(val); break;
+                case "objectModel": def.setObjectModel(val); break;
+                case "resultType": def.setResultTypeName(val); break;
+                case "saxon": def.setSaxon(val); break;
+                case "threadSafety": def.setThreadSafety(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected XQueryExpression doParseXQueryExpression() throws IOException, XmlPullParserException {
+        return doParse(new XQueryExpression(), (def, key, val) -> {
+            switch (key) {
+                case "headerName": def.setHeaderName(val); break;
+                case "type": def.setType(val); break;
+                default: return expressionDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), expressionDefinitionValueHandler());
+    }
+    protected CustomLoadBalancerDefinition doParseCustomLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new CustomLoadBalancerDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return identifiedTypeAttributeHandler().accept(def, key, val);
+        }, noElementHandler(), noValueHandler());
+    }
+    protected FailoverLoadBalancerDefinition doParseFailoverLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new FailoverLoadBalancerDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "maximumFailoverAttempts": def.setMaximumFailoverAttempts(val); break;
+                case "roundRobin": def.setRoundRobin(val); break;
+                case "sticky": def.setSticky(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("exception".equals(key)) {
+                doAdd(doParseText(), def.getExceptions(), def::setExceptions);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected RandomLoadBalancerDefinition doParseRandomLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RandomLoadBalancerDefinition(),
+            identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected RoundRobinLoadBalancerDefinition doParseRoundRobinLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RoundRobinLoadBalancerDefinition(),
+            identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected StickyLoadBalancerDefinition doParseStickyLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new StickyLoadBalancerDefinition(),
+            identifiedTypeAttributeHandler(), (def, key) -> {
+            if ("correlationExpression".equals(key)) {
+                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected TopicLoadBalancerDefinition doParseTopicLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new TopicLoadBalancerDefinition(),
+            identifiedTypeAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected WeightedLoadBalancerDefinition doParseWeightedLoadBalancerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new WeightedLoadBalancerDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "distributionRatio": def.setDistributionRatio(val); break;
+                case "distributionRatioDelimiter": def.setDistributionRatioDelimiter(val); break;
+                case "roundRobin": def.setRoundRobin(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected DeleteVerbDefinition doParseDeleteVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DeleteVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected <T extends VerbDefinition> AttributeHandler<T> verbDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "apiDocs": def.setApiDocs(val); break;
+                case "bindingMode": def.setBindingMode(val); break;
+                case "clientRequestValidation": def.setClientRequestValidation(val); break;
+                case "consumes": def.setConsumes(val); break;
+                case "enableCORS": def.setEnableCORS(val); break;
+                case "method": def.setMethod(val); break;
+                case "outType": def.setOutType(val); break;
+                case "produces": def.setProduces(val); break;
+                case "routeId": def.setRouteId(val); break;
+                case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(val); break;
+                case "type": def.setType(val); break;
+                case "uri": def.setUri(val); break;
+                default: return optionalIdentifiedDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        };
+    }
+    protected <T extends VerbDefinition> ElementHandler<T> verbDefinitionElementHandler() {
+        return (def, key) -> {
+            switch (key) {
+                case "param": doAdd(doParseRestOperationParamDefinition(), def.getParams(), def::setParams); break;
+                case "responseMessage": doAdd(doParseRestOperationResponseMsgDefinition(), def.getResponseMsgs(), def::setResponseMsgs); break;
+                case "security": doAdd(doParseSecurityDefinition(), def.getSecurity(), def::setSecurity); break;
+                case "to": def.setToOrRoute(doParseToDefinition()); break;
+                case "toD": def.setToOrRoute(doParseToDynamicDefinition()); break;
+                case "route": def.setToOrRoute(doParseRouteDefinition()); break;
+                default: return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+            }
+            return true;
+        };
+    }
+    protected VerbDefinition doParseVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new VerbDefinition(), verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected RestOperationParamDefinition doParseRestOperationParamDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestOperationParamDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "arrayType": def.setArrayType(val); break;
+                case "collectionFormat": def.setCollectionFormat(CollectionFormat.valueOf(val)); break;
+                case "dataFormat": def.setDataFormat(val); break;
+                case "dataType": def.setDataType(val); break;
+                case "defaultValue": def.setDefaultValue(val); break;
+                case "description": def.setDescription(val); break;
+                case "name": def.setName(val); break;
+                case "required": def.setRequired(Boolean.valueOf(val)); break;
+                case "type": def.setType(RestParamType.valueOf(val)); break;
+                default: return false;
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "value": doAdd(doParseText(), def.getAllowableValues(), def::setAllowableValues); break;
+                case "examples": doAdd(doParseRestPropertyDefinition(), def.getExamples(), def::setExamples); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RestOperationResponseMsgDefinition doParseRestOperationResponseMsgDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestOperationResponseMsgDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "code": def.setCode(val); break;
+                case "message": def.setMessage(val); break;
+                case "responseModel": def.setResponseModel(val); break;
+                default: return false;
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "examples": doAdd(doParseRestPropertyDefinition(), def.getExamples(), def::setExamples); break;
+                case "header": doAdd(doParseRestOperationResponseHeaderDefinition(), def.getHeaders(), def::setHeaders); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected SecurityDefinition doParseSecurityDefinition() throws IOException, XmlPullParserException {
+        return doParse(new SecurityDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "key": def.setKey(val); break;
+                case "scopes": def.setScopes(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected GetVerbDefinition doParseGetVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new GetVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected HeadVerbDefinition doParseHeadVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new HeadVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected PatchVerbDefinition doParsePatchVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PatchVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected PostVerbDefinition doParsePostVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PostVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected PutVerbDefinition doParsePutVerbDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PutVerbDefinition(),
+            verbDefinitionAttributeHandler(), verbDefinitionElementHandler(), noValueHandler());
+    }
+    protected RestConfigurationDefinition doParseRestConfigurationDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestConfigurationDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "apiComponent": def.setApiComponent(val); break;
+                case "apiContextIdPattern": def.setApiContextIdPattern(val); break;
+                case "apiContextListing": def.setApiContextListing(Boolean.valueOf(val)); break;
+                case "apiContextPath": def.setApiContextPath(val); break;
+                case "apiContextRouteId": def.setApiContextRouteId(val); break;
+                case "apiHost": def.setApiHost(val); break;
+                case "apiVendorExtension": def.setApiVendorExtension(Boolean.valueOf(val)); break;
+                case "bindingMode": def.setBindingMode(RestBindingMode.valueOf(val)); break;
+                case "clientRequestValidation": def.setClientRequestValidation(Boolean.valueOf(val)); break;
+                case "component": def.setComponent(val); break;
+                case "contextPath": def.setContextPath(val); break;
+                case "enableCORS": def.setEnableCORS(Boolean.valueOf(val)); break;
+                case "host": def.setHost(val); break;
+                case "hostNameResolver": def.setHostNameResolver(RestHostNameResolver.valueOf(val)); break;
+                case "jsonDataFormat": def.setJsonDataFormat(val); break;
+                case "port": def.setPort(val); break;
+                case "producerApiDoc": def.setProducerApiDoc(val); break;
+                case "producerComponent": def.setProducerComponent(val); break;
+                case "scheme": def.setScheme(val); break;
+                case "skipBindingOnErrorCode": def.setSkipBindingOnErrorCode(Boolean.valueOf(val)); break;
+                case "useXForwardHeaders": def.setUseXForwardHeaders(Boolean.valueOf(val)); break;
+                case "xmlDataFormat": def.setXmlDataFormat(val); break;
+                default: return false;
+            }
+            return true;
+        }, (def, key) -> {
+            switch (key) {
+                case "apiProperty": doAdd(doParseRestPropertyDefinition(), def.getApiProperties(), def::setApiProperties); break;
+                case "componentProperty": doAdd(doParseRestPropertyDefinition(), def.getComponentProperties(), def::setComponentProperties); break;
+                case "consumerProperty": doAdd(doParseRestPropertyDefinition(), def.getConsumerProperties(), def::setConsumerProperties); break;
+                case "corsHeaders": doAdd(doParseRestPropertyDefinition(), def.getCorsHeaders(), def::setCorsHeaders); break;
+                case "dataFormatProperty": doAdd(doParseRestPropertyDefinition(), def.getDataFormatProperties(), def::setDataFormatProperties); break;
+                case "endpointProperty": doAdd(doParseRestPropertyDefinition(), def.getEndpointProperties(), def::setEndpointProperties); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RestPropertyDefinition doParseRestPropertyDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestPropertyDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "key": def.setKey(val); break;
+                case "value": def.setValue(val); break;
+                default: return false;
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RestSecuritiesDefinition doParseRestSecuritiesDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestSecuritiesDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "apiKey": doAdd(doParseRestSecurityApiKey(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+                case "basicAuth": doAdd(doParseRestSecurityBasicAuth(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+                case "oauth2": doAdd(doParseRestSecurityOAuth2(), def.getSecurityDefinitions(), def::setSecurityDefinitions); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected RestOperationResponseHeaderDefinition doParseRestOperationResponseHeaderDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestOperationResponseHeaderDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "arrayType": def.setArrayType(val); break;
+                case "collectionFormat": def.setCollectionFormat(CollectionFormat.valueOf(val)); break;
+                case "dataFormat": def.setDataFormat(val); break;
+                case "dataType": def.setDataType(val); break;
+                case "description": def.setDescription(val); break;
+                case "example": def.setExample(val); break;
+                case "name": def.setName(val); break;
+                default: return false;
+            }
+            return true;
+        }, (def, key) -> {
+            if ("value".equals(key)) {
+                doAdd(doParseText(), def.getAllowableValues(), def::setAllowableValues);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected <T extends RestSecurityDefinition> AttributeHandler<T> restSecurityDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "description": def.setDescription(val); break;
+                case "key": def.setKey(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected RestSecurityApiKey doParseRestSecurityApiKey() throws IOException, XmlPullParserException {
+        return doParse(new RestSecurityApiKey(), (def, key, val) -> {
+            switch (key) {
+                case "inHeader": def.setInHeader(Boolean.valueOf(val)); break;
+                case "inQuery": def.setInQuery(Boolean.valueOf(val)); break;
+                case "name": def.setName(val); break;
+                default: return restSecurityDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected RestSecurityBasicAuth doParseRestSecurityBasicAuth() throws IOException, XmlPullParserException {
+        return doParse(new RestSecurityBasicAuth(),
+            restSecurityDefinitionAttributeHandler(), noElementHandler(), noValueHandler());
+    }
+    protected RestSecurityOAuth2 doParseRestSecurityOAuth2() throws IOException, XmlPullParserException {
+        return doParse(new RestSecurityOAuth2(), (def, key, val) -> {
+            switch (key) {
+                case "authorizationUrl": def.setAuthorizationUrl(val); break;
+                case "flow": def.setFlow(val); break;
+                case "tokenUrl": def.setTokenUrl(val); break;
+                default: return restSecurityDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("scopes".equals(key)) {
+                doAdd(doParseRestPropertyDefinition(), def.getScopes(), def::setScopes);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    public RestsDefinition parseRestsDefinition()
+            throws IOException, XmlPullParserException {
+        expectTag("rests");
+        return doParseRestsDefinition();
+    }
+    protected RestsDefinition doParseRestsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new RestsDefinition(),
+            optionalIdentifiedDefinitionAttributeHandler(), (def, key) -> {
+            if ("rest".equals(key)) {
+                doAdd(doParseRestDefinition(), def.getRests(), def::setRests);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected CustomTransformerDefinition doParseCustomTransformerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new CustomTransformerDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "className": def.setClassName(val); break;
+                case "ref": def.setRef(val); break;
+                default: return transformerDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected <T extends TransformerDefinition> AttributeHandler<T> transformerDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "fromType": def.setFromType(val); break;
+                case "scheme": def.setScheme(val); break;
+                case "toType": def.setToType(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected DataFormatTransformerDefinition doParseDataFormatTransformerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new DataFormatTransformerDefinition(), (def, key, val) -> {
+            if ("ref".equals(key)) {
+                def.setRef(val);
+                return true;
+            }
+            return transformerDefinitionAttributeHandler().accept(def, key, val);
+        }, (def, key) -> {
+            DataFormatDefinition v = doParseDataFormatDefinitionRef(key);
+            if (v != null) { 
+                def.setDataFormatType(v);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected EndpointTransformerDefinition doParseEndpointTransformerDefinition() throws IOException, XmlPullParserException {
+        return doParse(new EndpointTransformerDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "ref": def.setRef(val); break;
+                case "uri": def.setUri(val); break;
+                default: return transformerDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected TransformersDefinition doParseTransformersDefinition() throws IOException, XmlPullParserException {
+        return doParse(new TransformersDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "dataFormatTransformer": doAdd(doParseDataFormatTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+                case "endpointTransformer": doAdd(doParseEndpointTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+                case "customTransformer": doAdd(doParseCustomTransformerDefinition(), def.getTransformers(), def::setTransformers); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected CustomValidatorDefinition doParseCustomValidatorDefinition() throws IOException, XmlPullParserException {
+        return doParse(new CustomValidatorDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "className": def.setClassName(val); break;
+                case "ref": def.setRef(val); break;
+                default: return validatorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected <T extends ValidatorDefinition> AttributeHandler<T> validatorDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            if ("type".equals(key)) {
+                def.setType(val);
+                return true;
+            }
+            return false;
+        };
+    }
+    protected EndpointValidatorDefinition doParseEndpointValidatorDefinition() throws IOException, XmlPullParserException {
+        return doParse(new EndpointValidatorDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "ref": def.setRef(val); break;
+                case "uri": def.setUri(val); break;
+                default: return validatorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
+    protected PredicateValidatorDefinition doParsePredicateValidatorDefinition() throws IOException, XmlPullParserException {
+        return doParse(new PredicateValidatorDefinition(),
+            validatorDefinitionAttributeHandler(), (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpression(v);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
+    protected ValidatorsDefinition doParseValidatorsDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ValidatorsDefinition(),
+            noAttributeHandler(), (def, key) -> {
+            switch (key) {
+                case "endpointValidator": doAdd(doParseEndpointValidatorDefinition(), def.getValidators(), def::setValidators); break;
+                case "predicateValidator": doAdd(doParsePredicateValidatorDefinition(), def.getValidators(), def::setValidators); break;
+                case "customValidator": doAdd(doParseCustomValidatorDefinition(), def.getValidators(), def::setValidators); break;
+                default: return false;
+            }
+            return true;
+        }, noValueHandler());
+    }
+    protected ProcessorDefinition doParseProcessorDefinitionRef(String key) throws IOException, XmlPullParserException {
+        switch (key) {
+            case "aggregate": return doParseAggregateDefinition();
+            case "bean": return doParseBeanDefinition();
+            case "doCatch": return doParseCatchDefinition();
+            case "when": return doParseWhenDefinition();
+            case "choice": return doParseChoiceDefinition();
+            case "otherwise": return doParseOtherwiseDefinition();
+            case "circuitBreaker": return doParseCircuitBreakerDefinition();
+            case "claimCheck": return doParseClaimCheckDefinition();
+            case "convertBodyTo": return doParseConvertBodyDefinition();
+            case "delay": return doParseDelayDefinition();
+            case "dynamicRouter": return doParseDynamicRouterDefinition();
+            case "enrich": return doParseEnrichDefinition();
+            case "filter": return doParseFilterDefinition();
+            case "doFinally": return doParseFinallyDefinition();
+            case "idempotentConsumer": return doParseIdempotentConsumerDefinition();
+            case "inOnly": return doParseInOnlyDefinition();
+            case "inOut": return doParseInOutDefinition();
+            case "intercept": return doParseInterceptDefinition();
+            case "interceptFrom": return doParseInterceptFromDefinition();
+            case "interceptSendToEndpoint": return doParseInterceptSendToEndpointDefinition();
+            case "loadBalance": return doParseLoadBalanceDefinition();
+            case "log": return doParseLogDefinition();
+            case "loop": return doParseLoopDefinition();
+            case "marshal": return doParseMarshalDefinition();
+            case "multicast": return doParseMulticastDefinition();
+            case "onCompletion": return doParseOnCompletionDefinition();
+            case "onException": return doParseOnExceptionDefinition();
+            case "onFallback": return doParseOnFallbackDefinition();
+            case "pipeline": return doParsePipelineDefinition();
+            case "policy": return doParsePolicyDefinition();
+            case "pollEnrich": return doParsePollEnrichDefinition();
+            case "process": return doParseProcessDefinition();
+            case "recipientList": return doParseRecipientListDefinition();
+            case "removeHeader": return doParseRemoveHeaderDefinition();
+            case "removeHeaders": return doParseRemoveHeadersDefinition();
+            case "removeProperties": return doParseRemovePropertiesDefinition();
+            case "removeProperty": return doParseRemovePropertyDefinition();
+            case "resequence": return doParseResequenceDefinition();
+            case "rollback": return doParseRollbackDefinition();
+            case "route": return doParseRouteDefinition();
+            case "routingSlip": return doParseRoutingSlipDefinition();
+            case "saga": return doParseSagaDefinition();
+            case "sample": return doParseSamplingDefinition();
+            case "script": return doParseScriptDefinition();
+            case "setBody": return doParseSetBodyDefinition();
+            case "setExchangePattern": return doParseSetExchangePatternDefinition();
+            case "setHeader": return doParseSetHeaderDefinition();
+            case "setProperty": return doParseSetPropertyDefinition();
+            case "sort": return doParseSortDefinition();
+            case "split": return doParseSplitDefinition();
+            case "step": return doParseStepDefinition();
+            case "stop": return doParseStopDefinition();
+            case "threads": return doParseThreadsDefinition();
+            case "throttle": return doParseThrottleDefinition();
+            case "throwException": return doParseThrowExceptionDefinition();
+            case "to": return doParseToDefinition();
+            case "toD": return doParseToDynamicDefinition();
+            case "transacted": return doParseTransactedDefinition();
+            case "transform": return doParseTransformDefinition();
+            case "doTry": return doParseTryDefinition();
+            case "unmarshal": return doParseUnmarshalDefinition();
+            case "validate": return doParseValidateDefinition();
+            case "whenSkipSendToEndpoint": return doParseWhenSkipSendToEndpointDefinition();
+            case "wireTap": return doParseWireTapDefinition();
+            case "serviceCall": return doParseServiceCallDefinition();
+            default: return null;
+        }
+    }
+    protected ExpressionDefinition doParseExpressionDefinitionRef(String key) throws IOException, XmlPullParserException {
+        switch (key) {
+            case "expressionDefinition": return doParseExpressionDefinition();
+            case "constant": return doParseConstantExpression();
+            case "exchangeProperty": return doParseExchangePropertyExpression();
+            case "groovy": return doParseGroovyExpression();
+            case "header": return doParseHeaderExpression();
+            case "hl7terser": return doParseHl7TerserExpression();
+            case "jsonpath": return doParseJsonPathExpression();
+            case "language": return doParseLanguageExpression();
+            case "method": return doParseMethodCallExpression();
+            case "mvel": return doParseMvelExpression();
+            case "ognl": return doParseOgnlExpression();
+            case "ref": return doParseRefExpression();
+            case "simple": return doParseSimpleExpression();
+            case "spel": return doParseSpELExpression();
+            case "tokenize": return doParseTokenizerExpression();
+            case "xtokenize": return doParseXMLTokenizerExpression();
+            case "xpath": return doParseXPathExpression();
+            case "xquery": return doParseXQueryExpression();
+            default: return null;
+        }
+    }
+    protected DataFormatDefinition doParseDataFormatDefinitionRef(String key) throws IOException, XmlPullParserException {
+        switch (key) {
+            case "asn1": return doParseASN1DataFormat();
+            case "any23": return doParseAny23DataFormat();
+            case "avro": return doParseAvroDataFormat();
+            case "barcode": return doParseBarcodeDataFormat();
+            case "base64": return doParseBase64DataFormat();
+            case "beanio": return doParseBeanioDataFormat();
+            case "bindy": return doParseBindyDataFormat();
+            case "cbor": return doParseCBORDataFormat();
+            case "crypto": return doParseCryptoDataFormat();
+            case "csv": return doParseCsvDataFormat();
+            case "customDataFormat": return doParseCustomDataFormat();
+            case "fhirJson": return doParseFhirJsonDataFormat();
+            case "fhirXml": return doParseFhirXmlDataFormat();
+            case "flatpack": return doParseFlatpackDataFormat();
+            case "grok": return doParseGrokDataFormat();
+            case "gzipdeflater": return doParseGzipDataFormat();
+            case "hl7": return doParseHL7DataFormat();
+            case "ical": return doParseIcalDataFormat();
+            case "jacksonxml": return doParseJacksonXMLDataFormat();
+            case "jaxb": return doParseJaxbDataFormat();
+            case "jsonApi": return doParseJsonApiDataFormat();
+            case "json": return doParseJsonDataFormat();
+            case "lzf": return doParseLZFDataFormat();
+            case "mime-multipart": return doParseMimeMultipartDataFormat();
+            case "pgp": return doParsePGPDataFormat();
+            case "protobuf": return doParseProtobufDataFormat();
+            case "rss": return doParseRssDataFormat();
+            case "soapjaxb": return doParseSoapJaxbDataFormat();
+            case "syslog": return doParseSyslogDataFormat();
+            case "tarfile": return doParseTarFileDataFormat();
+            case "thrift": return doParseThriftDataFormat();
+            case "tidyMarkup": return doParseTidyMarkupDataFormat();
+            case "univocity-csv": return doParseUniVocityCsvDataFormat();
+            case "univocity-fixed": return doParseUniVocityFixedWidthDataFormat();
+            case "univocity-tsv": return doParseUniVocityTsvDataFormat();
+            case "secureXML": return doParseXMLSecurityDataFormat();
+            case "xstream": return doParseXStreamDataFormat();
+            case "xmlrpc": return doParseXmlRpcDataFormat();
+            case "yaml": return doParseYAMLDataFormat();
+            case "zipdeflater": return doParseZipDeflaterDataFormat();
+            case "zipfile": return doParseZipFileDataFormat();
+            default: return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java
new file mode 100644
index 0000000..1126078
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/MXParser.java
@@ -0,0 +1,3243 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+/*
+ * Copyright (c) 2003 Extreme! Lab, Indiana University. All rights reserved.
+ *
+ * This software is open source. See the bottom of this file for the license.
+ *
+ * $Id: MXParser.java,v 1.52 2006/11/09 18:29:37 aslom Exp $
+ */
+
+package org.apache.camel.xml.io;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+//TODO best handling of interning issues
+//   have isAllNewStringInterned ???
+
+//TODO handling surrogate pairs: http://www.unicode.org/unicode/faq/utf_bom.html#6
+
+//TODO review code for use of bufAbsoluteStart when keeping pos between next()/fillBuf()
+
+/**
+ * Absolutely minimal implementation of XMLPULL V1 API
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public class MXParser
+        implements XmlPullParser {
+    //NOTE: no interning of those strings --> by Java lang spec they MUST be already interned
+    protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace";
+    protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+    protected final static String FEATURE_XML_ROUNDTRIP =
+            //"http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+            "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
+    protected final static String FEATURE_NAMES_INTERNED =
+            "http://xmlpull.org/v1/doc/features.html#names-interned";
+    protected final static String PROPERTY_XMLDECL_VERSION =
+            "http://xmlpull.org/v1/doc/properties.html#xmldecl-version";
+    protected final static String PROPERTY_XMLDECL_STANDALONE =
+            "http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone";
+    protected final static String PROPERTY_XMLDECL_CONTENT =
+            "http://xmlpull.org/v1/doc/properties.html#xmldecl-content";
+    protected final static String PROPERTY_LOCATION =
+            "http://xmlpull.org/v1/doc/properties.html#location";
+
+    /**
+     * Implementation notice:
+     * the is instance variable that controls if newString() is interning.
+     * <p><b>NOTE:</b> newStringIntern <b>always</b> returns interned strings
+     * and newString MAY return interned String depending on this variable.
+     * <p><b>NOTE:</b> by default in this minimal implementation it is false!
+     */
+    protected boolean allStringsInterned;
+
+    protected void resetStringCache() {
+        //System.out.println("resetStringCache() minimum called");
+    }
+
+    protected String newString(char[] cbuf, int off, int len) {
+        return new String(cbuf, off, len);
+    }
+
+    protected String newStringIntern(char[] cbuf, int off, int len) {
+        return (new String(cbuf, off, len)).intern();
+    }
+
+    private static final boolean TRACE_SIZING = false;
+
+    // NOTE: features are not resettable and typically defaults to false ...
+    protected boolean processNamespaces;
+    protected boolean roundtripSupported;
+
+    // global parser state
+    protected String location;
+    protected int lineNumber;
+    protected int columnNumber;
+    protected boolean seenRoot;
+    protected boolean reachedEnd;
+    protected int eventType;
+    protected boolean emptyElementTag;
+    // element stack
+    protected int depth;
+    protected char[] elRawName[];
+    protected int elRawNameEnd[];
+    protected int elRawNameLine[];
+
+    protected String elName[];
+    protected String elPrefix[];
+    protected String elUri[];
+    //protected String elValue[];
+    protected int elNamespaceCount[];
+
+
+    /**
+     * Make sure that we have enough space to keep element stack if passed size.
+     * It will always create one additional slot then current depth
+     */
+    protected void ensureElementsCapacity() {
+        final int elStackSize = elName != null ? elName.length : 0;
+        if ((depth + 1) >= elStackSize) {
+            // we add at least one extra slot ...
+            final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
+            if (TRACE_SIZING) {
+                System.err.println("TRACE_SIZING elStackSize " + elStackSize + " ==> " + newSize);
+            }
+            final boolean needsCopying = elStackSize > 0;
+            String[] arr = null;
+            // reuse arr local variable slot
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
+            elName = arr;
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(elPrefix, 0, arr, 0, elStackSize);
+            elPrefix = arr;
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(elUri, 0, arr, 0, elStackSize);
+            elUri = arr;
+
+            int[] iarr = new int[newSize];
+            if (needsCopying) {
+                System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
+            } else {
+                // special initialization
+                iarr[0] = 0;
+            }
+            elNamespaceCount = iarr;
+
+            //TODO: avoid using element raw name ...
+            iarr = new int[newSize];
+            if (needsCopying) {
+                System.arraycopy(elRawNameEnd, 0, iarr, 0, elStackSize);
+            }
+            elRawNameEnd = iarr;
+
+            iarr = new int[newSize];
+            if (needsCopying) {
+                System.arraycopy(elRawNameLine, 0, iarr, 0, elStackSize);
+            }
+            elRawNameLine = iarr;
+
+            final char[][] carr = new char[newSize][];
+            if (needsCopying) {
+                System.arraycopy(elRawName, 0, carr, 0, elStackSize);
+            }
+            elRawName = carr;
+            //            arr = new String[newSize];
+            //            if(needsCopying) System.arraycopy(elLocalName, 0, arr, 0, elStackSize);
+            //            elLocalName = arr;
+            //            arr = new String[newSize];
+            //            if(needsCopying) System.arraycopy(elDefaultNs, 0, arr, 0, elStackSize);
+            //            elDefaultNs = arr;
+            //            int[] iarr = new int[newSize];
+            //            if(needsCopying) System.arraycopy(elNsStackPos, 0, iarr, 0, elStackSize);
+            //            for (int i = elStackSize; i < iarr.length; i++)
+            //            {
+            //                iarr[i] = (i > 0) ? -1 : 0;
+            //            }
+            //            elNsStackPos = iarr;
+            //assert depth < elName.length;
+        }
+    }
+
+
+    // attribute stack
+    protected int attributeCount;
+    protected String attributeName[];
+    protected int attributeNameHash[];
+    //protected int attributeNameStart[];
+    //protected int attributeNameEnd[];
+    protected String attributePrefix[];
+    protected String attributeUri[];
+    protected String attributeValue[];
+    //protected int attributeValueStart[];
+    //protected int attributeValueEnd[];
+
+
+    /**
+     * Make sure that in attributes temporary array is enough space.
+     */
+    protected void ensureAttributesCapacity(int size) {
+        final int attrPosSize = attributeName != null ? attributeName.length : 0;
+        if (size >= attrPosSize) {
+            final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+            if (TRACE_SIZING) {
+                System.err.println("TRACE_SIZING attrPosSize " + attrPosSize + " ==> " + newSize);
+            }
+            final boolean needsCopying = attrPosSize > 0;
+            String[] arr = null;
+
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(attributeName, 0, arr, 0, attrPosSize);
+            attributeName = arr;
+
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(attributePrefix, 0, arr, 0, attrPosSize);
+            attributePrefix = arr;
+
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(attributeUri, 0, arr, 0, attrPosSize);
+            attributeUri = arr;
+
+            arr = new String[newSize];
+            if (needsCopying) System.arraycopy(attributeValue, 0, arr, 0, attrPosSize);
+            attributeValue = arr;
+
+            if (!allStringsInterned) {
+                final int[] iarr = new int[newSize];
+                if (needsCopying) System.arraycopy(attributeNameHash, 0, iarr, 0, attrPosSize);
+                attributeNameHash = iarr;
+            }
+
+            arr = null;
+            // //assert attrUri.length > size
+        }
+    }
+
+    // namespace stack
+    protected int namespaceEnd;
+    protected String namespacePrefix[];
+    protected int namespacePrefixHash[];
+    protected String namespaceUri[];
+
+    protected void ensureNamespacesCapacity(int size) {
+        final int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
+        if (size >= namespaceSize) {
+            final int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+            if (TRACE_SIZING) {
+                System.err.println("TRACE_SIZING namespaceSize " + namespaceSize + " ==> " + newSize);
+            }
+            final String[] newNamespacePrefix = new String[newSize];
+            final String[] newNamespaceUri = new String[newSize];
+            if (namespacePrefix != null) {
+                System.arraycopy(
+                        namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
+                System.arraycopy(
+                        namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
+            }
+            namespacePrefix = newNamespacePrefix;
+            namespaceUri = newNamespaceUri;
+
+
+            if (!allStringsInterned) {
+                final int[] newNamespacePrefixHash = new int[newSize];
+                if (namespacePrefixHash != null) {
+                    System.arraycopy(
+                            namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
+                }
+                namespacePrefixHash = newNamespacePrefixHash;
+            }
+            //prefixesSize = newSize;
+            // //assert nsPrefixes.length > size && nsPrefixes.length == newSize
+        }
+    }
+
+    /**
+     * simplistic implementation of hash function that has <b>constant</b>
+     * time to compute - so it also means diminishing hash quality for long strings
+     * but for XML parsing it should be good enough ...
+     */
+    protected static final int fastHash(char ch[], int off, int len) {
+        if (len == 0) return 0;
+        //assert len >0
+        int hash = ch[off]; // hash at beginning
+        //try {
+        hash = (hash << 7) + ch[off + len - 1]; // hash at the end
+        //} catch(ArrayIndexOutOfBoundsException aie) {
+        //    aie.printStackTrace(); //should never happen ...
+        //    throw new RuntimeException("this is violation of pre-condition");
+        //}
+        if (len > 16) hash = (hash << 7) + ch[off + (len / 4)];  // 1/4 from beginning
+        if (len > 8) hash = (hash << 7) + ch[off + (len / 2)];  // 1/2 of string size ...
+        // notice that hash is at most done 3 times <<7 so shifted by 21 bits 8 bit value
+        // so max result == 29 bits so it is quite just below 31 bits for long (2^32) ...
+        //assert hash >= 0;
+        return hash;
+    }
+
+    // entity replacement stack
+    protected int entityEnd;
+
+    protected String entityName[];
+    protected char[] entityNameBuf[];
+    protected String entityReplacement[];
+    protected char[] entityReplacementBuf[];
+
+    protected int entityNameHash[];
+
+    protected void ensureEntityCapacity() {
+        final int entitySize = entityReplacementBuf != null ? entityReplacementBuf.length : 0;
+        if (entityEnd >= entitySize) {
+            final int newSize = entityEnd > 7 ? 2 * entityEnd : 8; // = lucky 7 + 1 //25
+            if (TRACE_SIZING) {
+                System.err.println("TRACE_SIZING entitySize " + entitySize + " ==> " + newSize);
+            }
+            final String[] newEntityName = new String[newSize];
+            final char[] newEntityNameBuf[] = new char[newSize][];
+            final String[] newEntityReplacement = new String[newSize];
+            final char[] newEntityReplacementBuf[] = new char[newSize][];
+            if (entityName != null) {
+                System.arraycopy(entityName, 0, newEntityName, 0, entityEnd);
+                System.arraycopy(entityNameBuf, 0, newEntityNameBuf, 0, entityEnd);
+                System.arraycopy(entityReplacement, 0, newEntityReplacement, 0, entityEnd);
+                System.arraycopy(entityReplacementBuf, 0, newEntityReplacementBuf, 0, entityEnd);
+            }
+            entityName = newEntityName;
+            entityNameBuf = newEntityNameBuf;
+            entityReplacement = newEntityReplacement;
+            entityReplacementBuf = newEntityReplacementBuf;
+
+            if (!allStringsInterned) {
+                final int[] newEntityNameHash = new int[newSize];
+                if (entityNameHash != null) {
+                    System.arraycopy(entityNameHash, 0, newEntityNameHash, 0, entityEnd);
+                }
+                entityNameHash = newEntityNameHash;
+            }
+        }
+    }
+
+    // input buffer management
+    protected static final int READ_CHUNK_SIZE = 8 * 1024; //max data chars in one read() call
+    protected Reader reader;
+    protected String inputEncoding;
+
+
+    protected int bufLoadFactor = 95;  // 99%
+    //protected int bufHardLimit;  // only matters when expanding
+
+    protected char buf[] = new char[
+            Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 256];
+    protected int bufSoftLimit = (bufLoadFactor * buf.length) / 100; // desirable size of buffer
+    protected boolean preventBufferCompaction;
+
+    protected int bufAbsoluteStart; // this is buf
+    protected int bufStart;
+    protected int bufEnd;
+    protected int pos;
+    protected int posStart;
+    protected int posEnd;
+
+    protected char pc[] = new char[
+            Runtime.getRuntime().freeMemory() > 1000000L ? READ_CHUNK_SIZE : 64];
+    protected int pcStart;
+    protected int pcEnd;
+
+
+    // parsing state
+    //protected boolean needsMore;
+    //protected boolean seenMarkup;
+    protected boolean usePC;
+
+
+    protected boolean seenStartTag;
+    protected boolean seenEndTag;
+    protected boolean pastEndTag;
+    protected boolean seenAmpersand;
+    protected boolean seenMarkup;
+    protected boolean seenDocdecl;
+
+    // transient variable set during each call to next/Token()
+    protected boolean tokenize;
+    protected String text;
+    protected String entityRefName;
+
+    protected String xmlDeclVersion;
+    protected Boolean xmlDeclStandalone;
+    protected String xmlDeclContent;
+
+    protected void reset() {
+        //System.out.println("reset() called");
+        location = null;
+        lineNumber = 1;
+        columnNumber = 0;
+        seenRoot = false;
+        reachedEnd = false;
+        eventType = START_DOCUMENT;
+        emptyElementTag = false;
+
+        depth = 0;
+
+        attributeCount = 0;
+
+        namespaceEnd = 0;
+
+        entityEnd = 0;
+
+        reader = null;
+        inputEncoding = null;
+
+        preventBufferCompaction = false;
+        bufAbsoluteStart = 0;
+        bufEnd = bufStart = 0;
+        pos = posStart = posEnd = 0;
+
+        pcEnd = pcStart = 0;
+
+        usePC = false;
+
+        seenStartTag = false;
+        seenEndTag = false;
+        pastEndTag = false;
+        seenAmpersand = false;
+        seenMarkup = false;
+        seenDocdecl = false;
+
+        xmlDeclVersion = null;
+        xmlDeclStandalone = null;
+        xmlDeclContent = null;
+
+        resetStringCache();
+    }
+
+    public MXParser() {
+    }
+
+
+    /**
+     * Method setFeature
+     *
+     * @param name  a  String
+     * @param state a  boolean
+     * @throws XmlPullParserException
+     */
+    public void setFeature(String name,
+                           boolean state) throws XmlPullParserException {
+        if (name == null) throw new IllegalArgumentException("feature name should not be null");
+        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+            if (eventType != START_DOCUMENT) throw new XmlPullParserException(
+                    "namespace processing feature can only be changed before parsing", this, null);
+            processNamespaces = state;
+            //        } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+            //      if(type != START_DOCUMENT) throw new XmlPullParserException(
+            //              "namespace reporting feature can only be changed before parsing", this, null);
+            //            reportNsAttribs = state;
+        } else if (FEATURE_NAMES_INTERNED.equals(name)) {
+            if (state != false) {
+                throw new XmlPullParserException(
+                        "interning names in this implementation is not supported");
+            }
+        } else if (FEATURE_PROCESS_DOCDECL.equals(name)) {
+            if (state != false) {
+                throw new XmlPullParserException(
+                        "processing DOCDECL is not supported");
+            }
+            //} else if(REPORT_DOCDECL.equals(name)) {
+            //    paramNotifyDoctype = state;
+        } else if (FEATURE_XML_ROUNDTRIP.equals(name)) {
+            //if(state == false) {
+            //    throw new XmlPullParserException(
+            //        "roundtrip feature can not be switched off");
+            //}
+            roundtripSupported = state;
+        } else {
+            throw new XmlPullParserException("unsupported feature " + name);
+        }
+    }
+
+    /**
+     * Unknown properties are <strong>always</strong> returned as false
+     */
+    public boolean getFeature(String name) {
+        if (name == null) throw new IllegalArgumentException("feature name should not be null");
+        if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
+            return processNamespaces;
+            //        } else if(FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
+            //            return reportNsAttribs;
+        } else if (FEATURE_NAMES_INTERNED.equals(name)) {
+            return false;
+        } else if (FEATURE_PROCESS_DOCDECL.equals(name)) {
+            return false;
+            //} else if(REPORT_DOCDECL.equals(name)) {
+            //    return paramNotifyDoctype;
+        } else if (FEATURE_XML_ROUNDTRIP.equals(name)) {
+            //return true;
+            return roundtripSupported;
+        }
+        return false;
+    }
+
+    public void setProperty(String name,
+                            Object value)
+            throws XmlPullParserException {
+        if (PROPERTY_LOCATION.equals(name)) {
+            location = (String) value;
+        } else {
+            throw new XmlPullParserException("unsupported property: '" + name + "'");
+        }
+    }
+
+
+    public Object getProperty(String name) {
+        if (name == null) throw new IllegalArgumentException("property name should not be null");
+        if (PROPERTY_XMLDECL_VERSION.equals(name)) {
+            return xmlDeclVersion;
+        } else if (PROPERTY_XMLDECL_STANDALONE.equals(name)) {
+            return xmlDeclStandalone;
+        } else if (PROPERTY_XMLDECL_CONTENT.equals(name)) {
+            return xmlDeclContent;
+        } else if (PROPERTY_LOCATION.equals(name)) {
+            return location;
+        }
+        return null;
+    }
+
+
+    public void setInput(Reader in) throws XmlPullParserException {
+        if (in == null) {
+            throw new IllegalArgumentException("input reader can not be null");
+        }
+        reset();
+        reader = in;
+    }
+
+    public void setInput(java.io.InputStream inputStream, String inputEncoding)
+            throws XmlPullParserException {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("input stream can not be null");
+        }
+        reset();
+        try {
+            if (inputEncoding != null) {
+                this.reader = new InputStreamReader(inputStream, inputEncoding);
+                this.inputEncoding = inputEncoding;
+            } else {
+                XmlStreamReader xr = new XmlStreamReader(inputStream);
+                this.reader = xr;
+                this.inputEncoding = xr.getEncoding();
+            }
+        } catch (IOException une) {
+            throw new XmlPullParserException(
+                    "could not create reader for encoding " + inputEncoding + " : " + une, this, une);
+        }
+    }
+
+    public String getInputEncoding() {
+        return inputEncoding;
+    }
+
+    public void defineEntityReplacementText(String entityName,
+                                            String replacementText)
+            throws XmlPullParserException {
+        //      throw new XmlPullParserException("not allowed");
+
+        //protected char[] entityReplacement[];
+        ensureEntityCapacity();
+
+        // this is to make sure that if interning works we will take advantage of it ...
+        this.entityName[entityEnd] = newString(entityName.toCharArray(), 0, entityName.length());
+        entityNameBuf[entityEnd] = entityName.toCharArray();
+
+        entityReplacement[entityEnd] = replacementText;
+        entityReplacementBuf[entityEnd] = replacementText.toCharArray();
+        if (!allStringsInterned) {
+            entityNameHash[entityEnd] =
+                    fastHash(entityNameBuf[entityEnd], 0, entityNameBuf[entityEnd].length);
+        }
+        ++entityEnd;
+        //TODO disallow < or & in entity replacement text (or ]]>???)
+        // TOOD keepEntityNormalizedForAttributeValue cached as well ...
+    }
+
+    public int getNamespaceCount(int depth)
+            throws XmlPullParserException {
+        if (processNamespaces == false || depth == 0) {
+            return 0;
+        }
+        //int maxDepth = eventType == END_TAG ? this.depth + 1 : this.depth;
+        //if(depth < 0 || depth > maxDepth) throw new IllegalArgumentException(
+        if (depth < 0 || depth > this.depth) throw new IllegalArgumentException(
+                "allowed namespace depth 0.." + this.depth + " not " + depth);
+        return elNamespaceCount[depth];
+    }
+
+    public String getNamespacePrefix(int pos)
+            throws XmlPullParserException {
+
+        //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+        //if(pos < end) {
+        if (pos < namespaceEnd) {
+            return namespacePrefix[pos];
+        } else {
+            throw new XmlPullParserException(
+                    "position " + pos + " exceeded number of available namespaces " + namespaceEnd);
+        }
+    }
+
+    public String getNamespaceUri(int pos) throws XmlPullParserException {
+        //int end = eventType == END_TAG ? elNamespaceCount[ depth + 1 ] : namespaceEnd;
+        //if(pos < end) {
+        if (pos < namespaceEnd) {
+            return namespaceUri[pos];
+        } else {
+            throw new XmlPullParserException(
+                    "position " + pos + " exceeded number of available namespaces " + namespaceEnd);
+        }
+    }
+
+    public String getNamespace(String prefix)
+    //throws XmlPullParserException
+    {
+        //int count = namespaceCount[ depth ];
+        if (prefix != null) {
+            for (int i = namespaceEnd - 1; i >= 0; i--) {
+                if (prefix.equals(namespacePrefix[i])) {
+                    return namespaceUri[i];
+                }
+            }
+            if ("xml".equals(prefix)) {
+                return XML_URI;
+            } else if ("xmlns".equals(prefix)) {
+                return XMLNS_URI;
+            }
+        } else {
+            for (int i = namespaceEnd - 1; i >= 0; i--) {
+                if (namespacePrefix[i] == null) { //"") { //null ) { //TODO check FIXME Alek
+                    return namespaceUri[i];
+                }
+            }
+
+        }
+        return null;
+    }
+
+
+    public int getDepth() {
+        return depth;
+    }
+
+
+    private static int findFragment(int bufMinPos, char[] b, int start, int end) {
+        //System.err.println("bufStart="+bufStart+" b="+printable(new String(b, start, end - start))+" start="+start+" end="+end);
+        if (start < bufMinPos) {
+            start = bufMinPos;
+            if (start > end) start = end;
+            return start;
+        }
+        if (end - start > 65) {
+            start = end - 10; // try to find good location
+        }
+        int i = start + 1;
+        while (--i > bufMinPos) {
+            if ((end - i) > 65) break;
+            final char c = b[i];
+            if (c == '<' && (start - i) > 10) break;
+        }
+        return i;
+    }
+
+
+    /**
+     * Return string describing current position of parsers as
+     * text 'STATE [seen %s...] @line:column'.
+     */
+    public String getPositionDescription() {
+        String fragment = null;
+        if (posStart <= pos) {
+            final int start = findFragment(0, buf, posStart, pos);
+            //System.err.println("start="+start);
+            if (start < pos) {
+                fragment = new String(buf, start, pos - start);
+            }
+            if (bufAbsoluteStart > 0 || start > 0) fragment = "..." + fragment;
+        }
+        //        return " at line "+tokenizerPosRow
+        //            +" and column "+(tokenizerPosCol-1)
+        //            +(fragment != null ? " seen "+printable(fragment)+"..." : "");
+        return " " + TYPES[eventType] +
+                (fragment != null ? " seen " + printable(fragment) + "..." : "")
+                + " " + (location != null ? location : "")
+                + "@" + getLineNumber() + ":" + getColumnNumber();
+    }
+
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
+    public int getColumnNumber() {
+        return columnNumber;
+    }
+
+
+    public boolean isWhitespace() throws XmlPullParserException {
+        if (eventType == TEXT || eventType == CDSECT) {
+            if (usePC) {
+                for (int i = pcStart; i < pcEnd; i++) {
+                    if (!isS(pc[i])) return false;
+                }
+                return true;
+            } else {
+                for (int i = posStart; i < posEnd; i++) {
+                    if (!isS(buf[i])) return false;
+                }
+                return true;
+            }
+        } else if (eventType == IGNORABLE_WHITESPACE) {
+            return true;
+        }
+        throw new XmlPullParserException("no content available to check for white spaces");
+    }
+
+    public String getText() {
+        if (eventType == START_DOCUMENT || eventType == END_DOCUMENT) {
+            //throw new XmlPullParserException("no content available to read");
+            //      if(roundtripSupported) {
+            //          text = new String(buf, posStart, posEnd - posStart);
+            //      } else {
+            return null;
+            //      }
+        } else if (eventType == ENTITY_REF) {
+            return text;
+        }
+        if (text == null) {
+            if (!usePC || eventType == START_TAG || eventType == END_TAG) {
+                text = new String(buf, posStart, posEnd - posStart);
+            } else {
+                text = new String(pc, pcStart, pcEnd - pcStart);
+            }
+        }
+        return text;
+    }
+
+    public char[] getTextCharacters(int[] holderForStartAndLength) {
+        if (eventType == TEXT) {
+            if (usePC) {
+                holderForStartAndLength[0] = pcStart;
+                holderForStartAndLength[1] = pcEnd - pcStart;
+                return pc;
+            } else {
+                holderForStartAndLength[0] = posStart;
+                holderForStartAndLength[1] = posEnd - posStart;
+                return buf;
+
+            }
+        } else if (eventType == START_TAG
+                || eventType == END_TAG
+                || eventType == CDSECT
+                || eventType == COMMENT
+                || eventType == ENTITY_REF
+                || eventType == PROCESSING_INSTRUCTION
+                || eventType == IGNORABLE_WHITESPACE
+                || eventType == DOCDECL) {
+            holderForStartAndLength[0] = posStart;
+            holderForStartAndLength[1] = posEnd - posStart;
+            return buf;
+        } else if (eventType == START_DOCUMENT
+                || eventType == END_DOCUMENT) {
+            //throw new XmlPullParserException("no content available to read");
+            holderForStartAndLength[0] = holderForStartAndLength[1] = -1;
+            return null;
+        } else {
+            throw new IllegalArgumentException("unknown text eventType: " + eventType);
+        }
+        //      String s = getText();
+        //      char[] cb = null;
+        //      if(s!= null) {
+        //          cb = s.toCharArray();
+        //          holderForStartAndLength[0] = 0;
+        //          holderForStartAndLength[1] = s.length();
+        //      } else {
+        //      }
+        //      return cb;
+    }
+
+    public String getNamespace() {
+        if (eventType == START_TAG) {
+            //return processNamespaces ? elUri[ depth - 1 ] : NO_NAMESPACE;
+            return processNamespaces ? elUri[depth] : NO_NAMESPACE;
+        } else if (eventType == END_TAG) {
+            return processNamespaces ? elUri[depth] : NO_NAMESPACE;
+        }
+        return null;
+        //        String prefix = elPrefix[ maxDepth ];
+        //        if(prefix != null) {
+        //            for( int i = namespaceEnd -1; i >= 0; i--) {
+        //                if( prefix.equals( namespacePrefix[ i ] ) ) {
+        //                    return namespaceUri[ i ];
+        //                }
+        //            }
+        //        } else {
+        //            for( int i = namespaceEnd -1; i >= 0; i--) {
+        //                if( namespacePrefix[ i ]  == null ) {
+        //                    return namespaceUri[ i ];
+        //                }
+        //            }
+        //
+        //        }
+        //        return "";
+    }
+
+    public String getName() {
+        if (eventType == START_TAG) {
+            //return elName[ depth - 1 ] ;
+            return elName[depth];
+        } else if (eventType == END_TAG) {
+            return elName[depth];
+        } else if (eventType == ENTITY_REF) {
+            if (entityRefName == null) {
+                entityRefName = newString(buf, posStart, posEnd - posStart);
+            }
+            return entityRefName;
+        } else {
+            return null;
+        }
+    }
+
+    public String getPrefix() {
+        if (eventType == START_TAG) {
+            //return elPrefix[ depth - 1 ] ;
+            return elPrefix[depth];
+        } else if (eventType == END_TAG) {
+            return elPrefix[depth];
+        }
+        return null;
+        //        if(eventType != START_TAG && eventType != END_TAG) return null;
+        //        int maxDepth = eventType == END_TAG ? depth : depth - 1;
+        //        return elPrefix[ maxDepth ];
+    }
+
+
+    public boolean isEmptyElementTag() throws XmlPullParserException {
+        if (eventType != START_TAG) throw new XmlPullParserException(
+                "parser must be on START_TAG to check for empty element", this, null);
+        return emptyElementTag;
+    }
+
+    public int getAttributeCount() {
+        if (eventType != START_TAG) return -1;
+        return attributeCount;
+    }
+
+    public String getAttributeNamespace(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (processNamespaces == false) return NO_NAMESPACE;
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return attributeUri[index];
+    }
+
+    public String getAttributeName(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return attributeName[index];
+    }
+
+    public String getAttributePrefix(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (processNamespaces == false) return null;
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return attributePrefix[index];
+    }
+
+    public String getAttributeType(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return "CDATA";
+    }
+
+    public boolean isAttributeDefault(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return false;
+    }
+
+    public String getAttributeValue(int index) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes");
+        if (index < 0 || index >= attributeCount) throw new IndexOutOfBoundsException(
+                "attribute position must be 0.." + (attributeCount - 1) + " and not " + index);
+        return attributeValue[index];
+    }
+
+    public String getAttributeValue(String namespace,
+                                    String name) {
+        if (eventType != START_TAG) throw new IndexOutOfBoundsException(
+                "only START_TAG can have attributes" + getPositionDescription());
+        if (name == null) {
+            throw new IllegalArgumentException("attribute name can not be null");
+        }
+        // TODO make check if namespace is interned!!! etc. for names!!!
+        if (processNamespaces) {
+            if (namespace == null) {
+                namespace = "";
+            }
+
+            for (int i = 0; i < attributeCount; ++i) {
+                if ((namespace == attributeUri[i] ||
+                        namespace.equals(attributeUri[i]))
+                        //(namespace != null && namespace.equals(attributeUri[ i ]))
+                        // taking advantage of String.intern()
+                        && name.equals(attributeName[i])) {
+                    return attributeValue[i];
+                }
+            }
+        } else {
+            if (namespace != null && namespace.length() == 0) {
+                namespace = null;
+            }
+            if (namespace != null) throw new IllegalArgumentException(
+                    "when namespaces processing is disabled attribute namespace must be null");
+            for (int i = 0; i < attributeCount; ++i) {
+                if (name.equals(attributeName[i])) {
+                    return attributeValue[i];
+                }
+            }
+        }
+        return null;
+    }
+
+
+    public int getEventType()
+            throws XmlPullParserException {
+        return eventType;
+    }
+
+    public void require(int type, String namespace, String name)
+            throws XmlPullParserException, IOException {
+        if (processNamespaces == false && namespace != null) {
+            throw new XmlPullParserException(
+                    "processing namespaces must be enabled on parser (or factory)" +
+                            " to have possible namespaces declared on elements"
+                            + (" (position:" + getPositionDescription()) + ")");
+        }
+        if (type != getEventType()
+                || (namespace != null && !namespace.equals(getNamespace()))
+                || (name != null && !name.equals(getName()))) {
+            throw new XmlPullParserException(
+                    "expected event " + TYPES[type]
+                            + (name != null ? " with name '" + name + "'" : "")
+                            + (namespace != null && name != null ? " and" : "")
+                            + (namespace != null ? " with namespace '" + namespace + "'" : "")
+                            + " but got"
+                            + (type != getEventType() ? " " + TYPES[getEventType()] : "")
+                            + (name != null && getName() != null && !name.equals(getName())
+                            ? " name '" + getName() + "'" : "")
+                            + (namespace != null && name != null
+                            && getName() != null && !name.equals(getName())
+                            && getNamespace() != null && !namespace.equals(getNamespace())
+                            ? " and" : "")
+                            + (namespace != null && getNamespace() != null && !namespace.equals(getNamespace())
+                            ? " namespace '" + getNamespace() + "'" : "")
+                            + (" (position:" + getPositionDescription()) + ")");
+        }
+    }
+
+
+    /**
+     * Skip sub tree that is currently parser positioned on.
+     * <br>NOTE: parser must be on START_TAG and when function returns
+     * parser will be positioned on corresponding END_TAG
+     */
+    public void skipSubTree()
+            throws XmlPullParserException, IOException {
+        require(START_TAG, null, null);
+        int level = 1;
+        while (level > 0) {
+            int eventType = next();
+            if (eventType == END_TAG) {
+                --level;
+            } else if (eventType == START_TAG) {
+                ++level;
+            }
+        }
+    }
+
+    //    public String readText() throws XmlPullParserException, IOException
+    //    {
+    //        if (getEventType() != TEXT) return "";
+    //        String result = getText();
+    //        next();
+    //        return result;
+    //    }
+
+    public String nextText() throws XmlPullParserException, IOException {
+        //        String result = null;
+        //        boolean onStartTag = false;
+        //        if(eventType == START_TAG) {
+        //            onStartTag = true;
+        //            next();
+        //        }
+        //        if(eventType == TEXT) {
+        //            result = getText();
+        //            next();
+        //        } else if(onStartTag && eventType == END_TAG) {
+        //            result = "";
+        //        } else {
+        //            throw new XmlPullParserException(
+        //                "parser must be on START_TAG or TEXT to read text", this, null);
+        //        }
+        //        if(eventType != END_TAG) {
+        //            throw new XmlPullParserException(
+        //                "event TEXT it must be immediately followed by END_TAG", this, null);
+        //        }
+        //        return result;
+        if (getEventType() != START_TAG) {
+            throw new XmlPullParserException(
+                    "parser must be on START_TAG to read next text", this, null);
+        }
+        int eventType = next();
+        if (eventType == TEXT) {
+            final String result = getText();
+            eventType = next();
+            if (eventType != END_TAG) {
+                throw new XmlPullParserException(
+                        "TEXT must be immediately followed by END_TAG and not "
+                                + TYPES[getEventType()], this, null);
+            }
+            return result;
+        } else if (eventType == END_TAG) {
+            return "";
+        } else {
+            throw new XmlPullParserException(
+                    "parser must be on START_TAG or TEXT to read text", this, null);
+        }
+    }
+
+    public int nextTag() throws XmlPullParserException, IOException {
+        next();
+        if (eventType == TEXT && isWhitespace()) {  // skip whitespace
+            next();
+        }
+        if (eventType != START_TAG && eventType != END_TAG) {
+            throw new XmlPullParserException("expected START_TAG or END_TAG not "
+                    + TYPES[getEventType()], this, null);
+        }
+        return eventType;
+    }
+
+    public int next()
+            throws XmlPullParserException, IOException {
+        tokenize = false;
+        return nextImpl();
+    }
+
+    public int nextToken()
+            throws XmlPullParserException, IOException {
+        tokenize = true;
+        return nextImpl();
+    }
+
+
+    protected int nextImpl()
+            throws XmlPullParserException, IOException {
+        text = null;
+        pcEnd = pcStart = 0;
+        usePC = false;
+        bufStart = posEnd;
+        if (pastEndTag) {
+            pastEndTag = false;
+            --depth;
+            namespaceEnd = elNamespaceCount[depth]; // less namespaces available
+        }
+        if (emptyElementTag) {
+            emptyElementTag = false;
+            pastEndTag = true;
+            return eventType = END_TAG;
+        }
+
+        // [1] document ::= prolog element Misc*
+        if (depth > 0) {
+
+            if (seenStartTag) {
+                seenStartTag = false;
+                return eventType = parseStartTag();
+            }
+            if (seenEndTag) {
+                seenEndTag = false;
+                return eventType = parseEndTag();
+            }
+
+            // ASSUMPTION: we are _on_ first character of content or markup!!!!
+            // [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
+            char ch;
+            if (seenMarkup) {  // we have read ahead ...
+                seenMarkup = false;
+                ch = '<';
+            } else if (seenAmpersand) {
+                seenAmpersand = false;
+                ch = '&';
+            } else {
+                ch = more();
+            }
+            posStart = pos - 1; // VERY IMPORTANT: this is correct start of event!!!
+
+            // when true there is some potential event TEXT to return - keep gathering
+            boolean hadCharData = false;
+
+            // when true TEXT data is not continual (like <![CDATA[text]]>) and requires PC merging
+            boolean needsMerging = false;
+
+            MAIN_LOOP:
+            while (true) {
+                // work on MARKUP
+                if (ch == '<') {
+                    if (hadCharData) {
+                        //posEnd = pos - 1;
+                        if (tokenize) {
+                            seenMarkup = true;
+                            return eventType = TEXT;
+                        }
+                    }
+                    ch = more();
+                    if (ch == '/') {
+                        if (!tokenize && hadCharData) {
+                            seenEndTag = true;
+                            //posEnd = pos - 2;
+                            return eventType = TEXT;
+                        }
+                        return eventType = parseEndTag();
+                    } else if (ch == '!') {
+                        ch = more();
+                        if (ch == '-') {
+                            // note: if(tokenize == false) posStart/End is NOT changed!!!!
+                            parseComment();
+                            if (tokenize) return eventType = COMMENT;
+                            if (!usePC && hadCharData) {
+                                needsMerging = true;
+                            } else {
+                                posStart = pos;  //completely ignore comment
+                            }
+                        } else if (ch == '[') {
+                            //posEnd = pos - 3;
+                            // must remember previous posStart/End as it merges with content of CDATA
+                            //int oldStart = posStart + bufAbsoluteStart;
+                            //int oldEnd = posEnd + bufAbsoluteStart;
+                            parseCDSect(hadCharData);
+                            if (tokenize) return eventType = CDSECT;
+                            final int cdStart = posStart;
+                            final int cdEnd = posEnd;
+                            final int cdLen = cdEnd - cdStart;
+
+
+                            if (cdLen > 0) { // was there anything inside CDATA section?
+                                hadCharData = true;
+                                if (!usePC) {
+                                    needsMerging = true;
+                                }
+                            }
+
+                            //                          posStart = oldStart;
+                            //                          posEnd = oldEnd;
+                            //                          if(cdLen > 0) { // was there anything inside CDATA section?
+                            //                              if(hadCharData) {
+                            //                                  // do merging if there was anything in CDSect!!!!
+                            //                                  //                                    if(!usePC) {
+                            //                                  //                                        // posEnd is correct already!!!
+                            //                                  //                                        if(posEnd > posStart) {
+                            //                                  //                                            joinPC();
+                            //                                  //                                        } else {
+                            //                                  //                                            usePC = true;
+                            //                                  //                                            pcStart = pcEnd = 0;
+                            //                                  //                                        }
+                            //                                  //                                    }
+                            //                                  //                                    if(pcEnd + cdLen >= pc.length) ensurePC(pcEnd + cdLen);
+                            //                                  //                                    // copy [cdStart..cdEnd) into PC
+                            //                                  //                                    System.arraycopy(buf, cdStart, pc, pcEnd, cdLen);
+                            //                                  //                                    pcEnd += cdLen;
+                            //                                  if(!usePC) {
+                            //                                      needsMerging = true;
+                            //                                      posStart = cdStart;
+                            //                                      posEnd = cdEnd;
+                            //                                  }
+                            //                              } else {
+                            //                                  if(!usePC) {
+                            //                                      needsMerging = true;
+                            //                                      posStart = cdStart;
+                            //                                      posEnd = cdEnd;
+                            //                                      hadCharData = true;
+                            //                                  }
+                            //                              }
+                            //                              //hadCharData = true;
+                            //                          } else {
+                            //                              if( !usePC && hadCharData ) {
+                            //                                  needsMerging = true;
+                            //                              }
+                            //                          }
+                        } else {
+                            throw new XmlPullParserException(
+                                    "unexpected character in markup " + printable(ch), this, null);
+                        }
+                    } else if (ch == '?') {
+                        parsePI();
+                        if (tokenize) return eventType = PROCESSING_INSTRUCTION;
+                        if (!usePC && hadCharData) {
+                            needsMerging = true;
+                        } else {
+                            posStart = pos;  //completely ignore PI
+                        }
+
+                    } else if (isNameStartChar(ch)) {
+                        if (!tokenize && hadCharData) {
+                            seenStartTag = true;
+                            //posEnd = pos - 2;
+                            return eventType = TEXT;
+                        }
+                        return eventType = parseStartTag();
+                    } else {
+                        throw new XmlPullParserException(
+                                "unexpected character in markup " + printable(ch), this, null);
+                    }
+                    // do content compaction if it makes sense!!!!
+
+                } else if (ch == '&') {
+                    // work on ENTITTY
+                    //posEnd = pos - 1;
+                    if (tokenize && hadCharData) {
+                        seenAmpersand = true;
+                        return eventType = TEXT;
+                    }
+                    final int oldStart = posStart + bufAbsoluteStart;
+                    final int oldEnd = posEnd + bufAbsoluteStart;
+                    final char[] resolvedEntity = parseEntityRef();
+                    if (tokenize) return eventType = ENTITY_REF;
+                    // check if replacement text can be resolved !!!
+                    if (resolvedEntity == null) {
+                        if (entityRefName == null) {
+                            entityRefName = newString(buf, posStart, posEnd - posStart);
+                        }
+                        throw new XmlPullParserException(
+                                "could not resolve entity named '" + printable(entityRefName) + "'",
+                                this, null);
+                    }
+                    //int entStart = posStart;
+                    //int entEnd = posEnd;
+                    posStart = oldStart - bufAbsoluteStart;
+                    posEnd = oldEnd - bufAbsoluteStart;
+                    if (!usePC) {
+                        if (hadCharData) {
+                            joinPC(); // posEnd is already set correctly!!!
+                            needsMerging = false;
+                        } else {
+                            usePC = true;
+                            pcStart = pcEnd = 0;
+                        }
+                    }
+                    //assert usePC == true;
+                    // write into PC replacement text - do merge for replacement text!!!!
+                    for (int i = 0; i < resolvedEntity.length; i++) {
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = resolvedEntity[i];
+
+                    }
+                    hadCharData = true;
+                    //assert needsMerging == false;
+                } else {
+
+                    if (needsMerging) {
+                        //assert usePC == false;
+                        joinPC();  // posEnd is already set correctly!!!
+                        //posStart = pos  -  1;
+                        needsMerging = false;
+                    }
+
+
+                    //no MARKUP not ENTITIES so work on character data ...
+
+
+                    // [14] CharData ::=   [^<&]* - ([^<&]* ']]>' [^<&]*)
+
+
+                    hadCharData = true;
+
+                    boolean normalizedCR = false;
+                    final boolean normalizeInput = tokenize == false || roundtripSupported == false;
+                    // use loop locality here!!!!
+                    boolean seenBracket = false;
+                    boolean seenBracketBracket = false;
+                    do {
+
+                        // check that ]]> does not show in
+                        if (ch == ']') {
+                            if (seenBracket) {
+                                seenBracketBracket = true;
+                            } else {
+                                seenBracket = true;
+                            }
+                        } else if (seenBracketBracket && ch == '>') {
+                            throw new XmlPullParserException(
+                                    "characters ]]> are not allowed in content", this, null);
+                        } else {
+                            if (seenBracket) {
+                                seenBracketBracket = seenBracket = false;
+                            }
+                            // assert seenTwoBrackets == seenBracket == false;
+                        }
+                        if (normalizeInput) {
+                            // deal with normalization issues ...
+                            if (ch == '\r') {
+                                normalizedCR = true;
+                                posEnd = pos - 1;
+                                // posEnd is already is set
+                                if (!usePC) {
+                                    if (posEnd > posStart) {
+                                        joinPC();
+                                    } else {
+                                        usePC = true;
+                                        pcStart = pcEnd = 0;
+                                    }
+                                }
+                                //assert usePC == true;
+                                if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                pc[pcEnd++] = '\n';
+                            } else if (ch == '\n') {
+                                //   if(!usePC) {  joinPC(); } else { if(pcEnd >= pc.length) ensurePC(); }
+                                if (!normalizedCR && usePC) {
+                                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                    pc[pcEnd++] = '\n';
+                                }
+                                normalizedCR = false;
+                            } else {
+                                if (usePC) {
+                                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                    pc[pcEnd++] = ch;
+                                }
+                                normalizedCR = false;
+                            }
+                        }
+
+                        ch = more();
+                    } while (ch != '<' && ch != '&');
+                    posEnd = pos - 1;
+                    continue MAIN_LOOP;  // skip ch = more() from below - we are alreayd ahead ...
+                }
+                ch = more();
+            } // endless while(true)
+        } else {
+            if (seenRoot) {
+                return parseEpilog();
+            } else {
+                return parseProlog();
+            }
+        }
+    }
+
+
+    protected int parseProlog()
+            throws XmlPullParserException, IOException {
+        // [2] prolog: ::= XMLDecl? Misc* (doctypedecl Misc*)? and look for [39] element
+
+        char ch;
+        if (seenMarkup) {
+            ch = buf[pos - 1];
+        } else {
+            ch = more();
+        }
+
+        if (eventType == START_DOCUMENT) {
+            // bootstrap parsing with getting first character input!
+            // deal with BOM
+            // detect BOM and drop it (Unicode int Order Mark)
+            if (ch == '\uFFFE') {
+                throw new XmlPullParserException(
+                        "first character in input was UNICODE noncharacter (0xFFFE)" +
+                                "- input requires int swapping", this, null);
+            }
+            if (ch == '\uFEFF') {
+                // skipping UNICODE int Order Mark (so called BOM)
+                ch = more();
+            }
+        }
+        seenMarkup = false;
+        boolean gotS = false;
+        posStart = pos - 1;
+        final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+        boolean normalizedCR = false;
+        while (true) {
+            // deal with Misc
+            // [27] Misc ::= Comment | PI | S
+            // deal with docdecl --> mark it!
+            // else parseStartTag seen <[^/]
+            if (ch == '<') {
+                if (gotS && tokenize) {
+                    posEnd = pos - 1;
+                    seenMarkup = true;
+                    return eventType = IGNORABLE_WHITESPACE;
+                }
+                ch = more();
+                if (ch == '?') {
+                    // check if it is 'xml'
+                    // deal with XMLDecl
+                    if (parsePI()) {  // make sure to skip XMLDecl
+                        if (tokenize) {
+                            return eventType = PROCESSING_INSTRUCTION;
+                        }
+                    } else {
+                        // skip over - continue tokenizing
+                        posStart = pos;
+                        gotS = false;
+                    }
+
+                } else if (ch == '!') {
+                    ch = more();
+                    if (ch == 'D') {
+                        if (seenDocdecl) {
+                            throw new XmlPullParserException(
+                                    "only one docdecl allowed in XML document", this, null);
+                        }
+                        seenDocdecl = true;
+                        parseDocdecl();
+                        if (tokenize) return eventType = DOCDECL;
+                    } else if (ch == '-') {
+                        parseComment();
+                        if (tokenize) return eventType = COMMENT;
+                    } else {
+                        throw new XmlPullParserException(
+                                "unexpected markup <!" + printable(ch), this, null);
+                    }
+                } else if (ch == '/') {
+                    throw new XmlPullParserException(
+                            "expected start tag name and not " + printable(ch), this, null);
+                } else if (isNameStartChar(ch)) {
+                    seenRoot = true;
+                    return parseStartTag();
+                } else {
+                    throw new XmlPullParserException(
+                            "expected start tag name and not " + printable(ch), this, null);
+                }
+            } else if (isS(ch)) {
+                gotS = true;
+                if (normalizeIgnorableWS) {
+                    if (ch == '\r') {
+                        normalizedCR = true;
+                        //posEnd = pos -1;
+                        //joinPC();
+                        // posEnd is already is set
+                        if (!usePC) {
+                            posEnd = pos - 1;
+                            if (posEnd > posStart) {
+                                joinPC();
+                            } else {
+                                usePC = true;
+                                pcStart = pcEnd = 0;
+                            }
+                        }
+                        //assert usePC == true;
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = '\n';
+                    } else if (ch == '\n') {
+                        if (!normalizedCR && usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = '\n';
+                        }
+                        normalizedCR = false;
+                    } else {
+                        if (usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = ch;
+                        }
+                        normalizedCR = false;
+                    }
+                }
+            } else {
+                throw new XmlPullParserException(
+                        "only whitespace content allowed before start tag and not " + printable(ch),
+                        this, null);
+            }
+            ch = more();
+        }
+    }
+
+    protected int parseEpilog()
+            throws XmlPullParserException, IOException {
+        if (eventType == END_DOCUMENT) {
+            throw new XmlPullParserException("already reached end of XML input", this, null);
+        }
+        if (reachedEnd) {
+            return eventType = END_DOCUMENT;
+        }
+        boolean gotS = false;
+        final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+        boolean normalizedCR = false;
+        try {
+            // epilog: Misc*
+            char ch;
+            if (seenMarkup) {
+                ch = buf[pos - 1];
+            } else {
+                ch = more();
+            }
+            seenMarkup = false;
+            posStart = pos - 1;
+            if (!reachedEnd) {
+                while (true) {
+                    // deal with Misc
+                    // [27] Misc ::= Comment | PI | S
+                    if (ch == '<') {
+                        if (gotS && tokenize) {
+                            posEnd = pos - 1;
+                            seenMarkup = true;
+                            return eventType = IGNORABLE_WHITESPACE;
+                        }
+                        ch = more();
+                        if (reachedEnd) {
+                            break;
+                        }
+                        if (ch == '?') {
+                            // check if it is 'xml'
+                            // deal with XMLDecl
+                            parsePI();
+                            if (tokenize) return eventType = PROCESSING_INSTRUCTION;
+
+                        } else if (ch == '!') {
+                            ch = more();
+                            if (reachedEnd) {
+                                break;
+                            }
+                            if (ch == 'D') {
+                                parseDocdecl(); //FIXME
+                                if (tokenize) return eventType = DOCDECL;
+                            } else if (ch == '-') {
+                                parseComment();
+                                if (tokenize) return eventType = COMMENT;
+                            } else {
+                                throw new XmlPullParserException(
+                                        "unexpected markup <!" + printable(ch), this, null);
+                            }
+                        } else if (ch == '/') {
+                            throw new XmlPullParserException(
+                                    "end tag not allowed in epilog but got " + printable(ch), this, null);
+                        } else if (isNameStartChar(ch)) {
+                            throw new XmlPullParserException(
+                                    "start tag not allowed in epilog but got " + printable(ch), this, null);
+                        } else {
+                            throw new XmlPullParserException(
+                                    "in epilog expected ignorable content and not " + printable(ch),
+                                    this, null);
+                        }
+                    } else if (isS(ch)) {
+                        gotS = true;
+                        if (normalizeIgnorableWS) {
+                            if (ch == '\r') {
+                                normalizedCR = true;
+                                //posEnd = pos -1;
+                                //joinPC();
+                                // posEnd is alreadys set
+                                if (!usePC) {
+                                    posEnd = pos - 1;
+                                    if (posEnd > posStart) {
+                                        joinPC();
+                                    } else {
+                                        usePC = true;
+                                        pcStart = pcEnd = 0;
+                                    }
+                                }
+                                //assert usePC == true;
+                                if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                pc[pcEnd++] = '\n';
+                            } else if (ch == '\n') {
+                                if (!normalizedCR && usePC) {
+                                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                    pc[pcEnd++] = '\n';
+                                }
+                                normalizedCR = false;
+                            } else {
+                                if (usePC) {
+                                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                                    pc[pcEnd++] = ch;
+                                }
+                                normalizedCR = false;
+                            }
+                        }
+                    } else {
+                        throw new XmlPullParserException(
+                                "in epilog non whitespace content is not allowed but got " + printable(ch),
+                                this, null);
+                    }
+                    ch = more();
+                    if (reachedEnd) {
+                        break;
+                    }
+
+                }
+            }
+
+            // throw Exception("unexpected content in epilog
+            // catch EOFException return END_DOCUEMENT
+            //try {
+        } catch (EOFException ex) {
+            reachedEnd = true;
+        }
+        if (reachedEnd) {
+            if (tokenize && gotS) {
+                posEnd = pos; // well - this is LAST available character pos
+                return eventType = IGNORABLE_WHITESPACE;
+            }
+            return eventType = END_DOCUMENT;
+        } else {
+            throw new XmlPullParserException("internal error in parseEpilog");
+        }
+    }
+
+
+    public int parseEndTag() throws XmlPullParserException, IOException {
+        //ASSUMPTION ch is past "</"
+        // [42] ETag ::=  '</' Name S? '>'
+        char ch = more();
+        if (!isNameStartChar(ch)) {
+            throw new XmlPullParserException(
+                    "expected name start and not " + printable(ch), this, null);
+        }
+        posStart = pos - 3;
+        final int nameStart = pos - 1 + bufAbsoluteStart;
+        do {
+            ch = more();
+        } while (isNameChar(ch));
+
+        // now we go one level down -- do checks
+        //--depth;  //FIXME
+
+        // check that end tag name is the same as start tag
+        //String name = new String(buf, nameStart - bufAbsoluteStart,
+        //                           (pos - 1) - (nameStart - bufAbsoluteStart));
+        //int last = pos - 1;
+        int off = nameStart - bufAbsoluteStart;
+        //final int len = last - off;
+        final int len = (pos - 1) - off;
+        final char[] cbuf = elRawName[depth];
+        if (elRawNameEnd[depth] != len) {
+            // construct strings for exception
+            final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+            final String endname = new String(buf, off, len);
+            throw new XmlPullParserException(
+                    "end tag name </" + endname + "> must match start tag name <" + startname + ">"
+                            + " from line " + elRawNameLine[depth], this, null);
+        }
+        for (int i = 0; i < len; i++) {
+            if (buf[off++] != cbuf[i]) {
+                // construct strings for exception
+                final String startname = new String(cbuf, 0, len);
+                final String endname = new String(buf, off - i - 1, len);
+                throw new XmlPullParserException(
+                        "end tag name </" + endname + "> must be the same as start tag <" + startname + ">"
+                                + " from line " + elRawNameLine[depth], this, null);
+            }
+        }
+
+        while (isS(ch)) {
+            ch = more();
+        } // skip additional white spaces
+        if (ch != '>') {
+            throw new XmlPullParserException(
+                    "expected > to finish end tag not " + printable(ch)
+                            + " from line " + elRawNameLine[depth], this, null);
+        }
+
+
+        //namespaceEnd = elNamespaceCount[ depth ]; //FIXME
+
+        posEnd = pos;
+        pastEndTag = true;
+        return eventType = END_TAG;
+    }
+
+    public int parseStartTag() throws XmlPullParserException, IOException {
+        //ASSUMPTION ch is past <T
+        // [40] STag ::=  '<' Name (S Attribute)* S? '>'
+        // [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
+        ++depth; //FIXME
+
+        posStart = pos - 2;
+
+        emptyElementTag = false;
+        attributeCount = 0;
+        // retrieve name
+        final int nameStart = pos - 1 + bufAbsoluteStart;
+        int colonPos = -1;
+        char ch = buf[pos - 1];
+        if (ch == ':' && processNamespaces) throw new XmlPullParserException(
+                "when namespaces processing enabled colon can not be at element name start",
+                this, null);
+        while (true) {
+            ch = more();
+            if (!isNameChar(ch)) break;
+            if (ch == ':' && processNamespaces) {
+                if (colonPos != -1) throw new XmlPullParserException(
+                        "only one colon is allowed in name of element when namespaces are enabled",
+                        this, null);
+                colonPos = pos - 1 + bufAbsoluteStart;
+            }
+        }
+
+        // retrieve name
+        ensureElementsCapacity();
+
+
+        //TODO check for efficient interning and then use elRawNameInterned!!!!
+
+        int elLen = (pos - 1) - (nameStart - bufAbsoluteStart);
+        if (elRawName[depth] == null || elRawName[depth].length < elLen) {
+            elRawName[depth] = new char[2 * elLen];
+        }
+        System.arraycopy(buf, nameStart - bufAbsoluteStart, elRawName[depth], 0, elLen);
+        elRawNameEnd[depth] = elLen;
+        elRawNameLine[depth] = lineNumber;
+
+        String name = null;
+
+        // work on prefixes and namespace URI
+        String prefix = null;
+        if (processNamespaces) {
+            if (colonPos != -1) {
+                prefix = elPrefix[depth] = newString(buf, nameStart - bufAbsoluteStart,
+                        colonPos - nameStart);
+                name = elName[depth] = newString(buf, colonPos + 1 - bufAbsoluteStart,
+                        //(pos -1) - (colonPos + 1));
+                        pos - 2 - (colonPos - bufAbsoluteStart));
+            } else {
+                prefix = elPrefix[depth] = null;
+                name = elName[depth] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+            }
+        } else {
+
+            name = elName[depth] = newString(buf, nameStart - bufAbsoluteStart, elLen);
+
+        }
+
+
+        while (true) {
+
+            while (isS(ch)) {
+                ch = more();
+            } // skip additional white spaces
+
+            if (ch == '>') {
+                break;
+            } else if (ch == '/') {
+                if (emptyElementTag) throw new XmlPullParserException(
+                        "repeated / in tag declaration", this, null);
+                emptyElementTag = true;
+                ch = more();
+                if (ch != '>') throw new XmlPullParserException(
+                        "expected > to end empty tag not " + printable(ch), this, null);
+                break;
+            } else if (isNameStartChar(ch)) {
+                ch = parseAttribute();
+                ch = more();
+                continue;
+            } else {
+                throw new XmlPullParserException(
+                        "start tag unexpected character " + printable(ch), this, null);
+            }
+            //ch = more(); // skip space
+        }
+
+        // now when namespaces were declared we can resolve them
+        if (processNamespaces) {
+            String uri = getNamespace(prefix);
+            if (uri == null) {
+                if (prefix == null) { // no prefix and no uri => use default namespace
+                    uri = NO_NAMESPACE;
+                } else {
+                    throw new XmlPullParserException(
+                            "could not determine namespace bound to element prefix " + prefix,
+                            this, null);
+                }
+
+            }
+            elUri[depth] = uri;
+
+
+            //String uri = getNamespace(prefix);
+            //if(uri == null && prefix == null) { // no prefix and no uri => use default namespace
+            //  uri = "";
+            //}
+            // resolve attribute namespaces
+            for (int i = 0; i < attributeCount; i++) {
+                final String attrPrefix = attributePrefix[i];
+                if (attrPrefix != null) {
+                    final String attrUri = getNamespace(attrPrefix);
+                    if (attrUri == null) {
+                        throw new XmlPullParserException(
+                                "could not determine namespace bound to attribute prefix " + attrPrefix,
+                                this, null);
+
+                    }
+                    attributeUri[i] = attrUri;
+                } else {
+                    attributeUri[i] = NO_NAMESPACE;
+                }
+            }
+
+            //TODO
+            //[ WFC: Unique Att Spec ]
+            // check attribute uniqueness constraint for attributes that has namespace!!!
+
+            for (int i = 1; i < attributeCount; i++) {
+                for (int j = 0; j < i; j++) {
+                    if (attributeUri[j] == attributeUri[i]
+                            && (allStringsInterned && attributeName[j].equals(attributeName[i])
+                            || (!allStringsInterned
+                            && attributeNameHash[j] == attributeNameHash[i]
+                            && attributeName[j].equals(attributeName[i])))
+
+                    ) {
+                        // prepare data for nice error message?
+                        String attr1 = attributeName[j];
+                        if (attributeUri[j] != null) attr1 = attributeUri[j] + ":" + attr1;
+                        String attr2 = attributeName[i];
+                        if (attributeUri[i] != null) attr2 = attributeUri[i] + ":" + attr2;
+                        throw new XmlPullParserException(
+                                "duplicated attributes " + attr1 + " and " + attr2, this, null);
+                    }
+                }
+            }
+
+
+        } else { // ! processNamespaces
+
+            //[ WFC: Unique Att Spec ]
+            // check raw attribute uniqueness constraint!!!
+            for (int i = 1; i < attributeCount; i++) {
+                for (int j = 0; j < i; j++) {
+                    if ((allStringsInterned && attributeName[j].equals(attributeName[i])
+                            || (!allStringsInterned
+                            && attributeNameHash[j] == attributeNameHash[i]
+                            && attributeName[j].equals(attributeName[i])))
+
+                    ) {
+                        // prepare data for nice error message?
+                        final String attr1 = attributeName[j];
+                        final String attr2 = attributeName[i];
+                        throw new XmlPullParserException(
+                                "duplicated attributes " + attr1 + " and " + attr2, this, null);
+                    }
+                }
+            }
+        }
+
+        elNamespaceCount[depth] = namespaceEnd;
+        posEnd = pos;
+        return eventType = START_TAG;
+    }
+
+    protected char parseAttribute() throws XmlPullParserException, IOException {
+        // parse attribute
+        // [41] Attribute ::= Name Eq AttValue
+        // [WFC: No External Entity References]
+        // [WFC: No < in Attribute Values]
+        final int prevPosStart = posStart + bufAbsoluteStart;
+        final int nameStart = pos - 1 + bufAbsoluteStart;
+        int colonPos = -1;
+        char ch = buf[pos - 1];
+        if (ch == ':' && processNamespaces) throw new XmlPullParserException(
+                "when namespaces processing enabled colon can not be at attribute name start",
+                this, null);
+
+
+        boolean startsWithXmlns = processNamespaces && ch == 'x';
+        int xmlnsPos = 0;
+
+        ch = more();
+        while (isNameChar(ch)) {
+            if (processNamespaces) {
+                if (startsWithXmlns && xmlnsPos < 5) {
+                    ++xmlnsPos;
+                    if (xmlnsPos == 1) {
+                        if (ch != 'm') startsWithXmlns = false;
+                    } else if (xmlnsPos == 2) {
+                        if (ch != 'l') startsWithXmlns = false;
+                    } else if (xmlnsPos == 3) {
+                        if (ch != 'n') startsWithXmlns = false;
+                    } else if (xmlnsPos == 4) {
+                        if (ch != 's') startsWithXmlns = false;
+                    } else {
+                        if (ch != ':') throw new XmlPullParserException(
+                                "after xmlns in attribute name must be colon"
+                                        + " when namespaces are enabled", this, null);
+                        //colonPos = pos - 1 + bufAbsoluteStart;
+                    }
+                }
+                if (ch == ':') {
+                    if (colonPos != -1) throw new XmlPullParserException(
+                            "only one colon is allowed in attribute name"
+                                    + " when namespaces are enabled", this, null);
+                    colonPos = pos - 1 + bufAbsoluteStart;
+                }
+            }
+            ch = more();
+        }
+
+        ensureAttributesCapacity(attributeCount);
+
+        // --- start processing attributes
+        String name = null;
+        String prefix = null;
+        // work on prefixes and namespace URI
+        if (processNamespaces) {
+            if (xmlnsPos < 4) startsWithXmlns = false;
+            if (startsWithXmlns) {
+                if (colonPos != -1) {
+                    //prefix = attributePrefix[ attributeCount ] = null;
+                    final int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+                    if (nameLen == 0) {
+                        throw new XmlPullParserException(
+                                "namespace prefix is required after xmlns: "
+                                        + " when namespaces are enabled", this, null);
+                    }
+                    name = //attributeName[ attributeCount ] =
+                            newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+                    //pos - 1 - (colonPos + 1 - bufAbsoluteStart)
+                }
+            } else {
+                if (colonPos != -1) {
+                    int prefixLen = colonPos - nameStart;
+                    prefix = attributePrefix[attributeCount] =
+                            newString(buf, nameStart - bufAbsoluteStart, prefixLen);
+                    //colonPos - (nameStart - bufAbsoluteStart));
+                    int nameLen = pos - 2 - (colonPos - bufAbsoluteStart);
+                    name = attributeName[attributeCount] =
+                            newString(buf, colonPos - bufAbsoluteStart + 1, nameLen);
+                    //pos - 1 - (colonPos + 1 - bufAbsoluteStart));
+
+                    //name.substring(0, colonPos-nameStart);
+                } else {
+                    prefix = attributePrefix[attributeCount] = null;
+                    name = attributeName[attributeCount] =
+                            newString(buf, nameStart - bufAbsoluteStart,
+                                    pos - 1 - (nameStart - bufAbsoluteStart));
+                }
+                if (!allStringsInterned) {
+                    attributeNameHash[attributeCount] = name.hashCode();
+                }
+            }
+
+        } else {
+            // retrieve name
+            name = attributeName[attributeCount] =
+                    newString(buf, nameStart - bufAbsoluteStart,
+                            pos - 1 - (nameStart - bufAbsoluteStart));
+            ////assert name != null;
+            if (!allStringsInterned) {
+                attributeNameHash[attributeCount] = name.hashCode();
+            }
+        }
+
+        // [25] Eq ::=  S? '=' S?
+        while (isS(ch)) {
+            ch = more();
+        } // skip additional spaces
+        if (ch != '=') throw new XmlPullParserException(
+                "expected = after attribute name", this, null);
+        ch = more();
+        while (isS(ch)) {
+            ch = more();
+        } // skip additional spaces
+
+        // [10] AttValue ::=   '"' ([^<&"] | Reference)* '"'
+        //                  |  "'" ([^<&'] | Reference)* "'"
+        final char delimit = ch;
+        if (delimit != '"' && delimit != '\'') throw new XmlPullParserException(
+                "attribute value must start with quotation or apostrophe not "
+                        + printable(delimit), this, null);
+        // parse until delimit or < and resolve Reference
+        //[67] Reference ::= EntityRef | CharRef
+        //int valueStart = pos + bufAbsoluteStart;
+
+
+        boolean normalizedCR = false;
+        usePC = false;
+        pcStart = pcEnd;
+        posStart = pos;
+
+        while (true) {
+            ch = more();
+            if (ch == delimit) {
+                break;
+            }
+            if (ch == '<') {
+                throw new XmlPullParserException(
+                        "markup not allowed inside attribute value - illegal < ", this, null);
+            }
+            if (ch == '&') {
+                // extractEntityRef
+                posEnd = pos - 1;
+                if (!usePC) {
+                    final boolean hadCharData = posEnd > posStart;
+                    if (hadCharData) {
+                        // posEnd is already set correctly!!!
+                        joinPC();
+                    } else {
+                        usePC = true;
+                        pcStart = pcEnd = 0;
+                    }
+                }
+                //assert usePC == true;
+
+                final char[] resolvedEntity = parseEntityRef();
+                // check if replacement text can be resolved !!!
+                if (resolvedEntity == null) {
+                    if (entityRefName == null) {
+                        entityRefName = newString(buf, posStart, posEnd - posStart);
+                    }
+                    throw new XmlPullParserException(
+                            "could not resolve entity named '" + printable(entityRefName) + "'",
+                            this, null);
+                }
+                // write into PC replacement text - do merge for replacement text!!!!
+                for (int i = 0; i < resolvedEntity.length; i++) {
+                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                    pc[pcEnd++] = resolvedEntity[i];
+                }
+            } else if (ch == '\t' || ch == '\n' || ch == '\r') {
+                // do attribute value normalization
+                // as described in http://www.w3.org/TR/REC-xml#AVNormalize
+                // TODO add test for it form spec ...
+                // handle EOL normalization ...
+                if (!usePC) {
+                    posEnd = pos - 1;
+                    if (posEnd > posStart) {
+                        joinPC();
+                    } else {
+                        usePC = true;
+                        pcEnd = pcStart = 0;
+                    }
+                }
+                //assert usePC == true;
+                if (pcEnd >= pc.length) ensurePC(pcEnd);
+                if (ch != '\n' || !normalizedCR) {
+                    pc[pcEnd++] = ' '; //'\n';
+                }
+
+            } else {
+                if (usePC) {
+                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                    pc[pcEnd++] = ch;
+                }
+            }
+            normalizedCR = ch == '\r';
+        }
+
+
+        if (processNamespaces && startsWithXmlns) {
+            String ns = null;
+            if (!usePC) {
+                ns = newStringIntern(buf, posStart, pos - 1 - posStart);
+            } else {
+                ns = newStringIntern(pc, pcStart, pcEnd - pcStart);
+            }
+            ensureNamespacesCapacity(namespaceEnd);
+            int prefixHash = -1;
+            if (colonPos != -1) {
+                if (ns.length() == 0) {
+                    throw new XmlPullParserException(
+                            "non-default namespace can not be declared to be empty string", this, null);
+                }
+                // declare new namespace
+                namespacePrefix[namespaceEnd] = name;
+                if (!allStringsInterned) {
+                    prefixHash = namespacePrefixHash[namespaceEnd] = name.hashCode();
+                }
+            } else {
+                // declare  new default namespace ...
+                namespacePrefix[namespaceEnd] = null; //""; //null; //TODO check FIXME Alek
+                if (!allStringsInterned) {
+                    prefixHash = namespacePrefixHash[namespaceEnd] = -1;
+                }
+            }
+            namespaceUri[namespaceEnd] = ns;
+
+            // detect duplicate namespace declarations!!!
+            final int startNs = elNamespaceCount[depth - 1];
+            for (int i = namespaceEnd - 1; i >= startNs; --i) {
+                if (((allStringsInterned || name == null) && namespacePrefix[i] == name)
+                        || (!allStringsInterned && name != null &&
+                        namespacePrefixHash[i] == prefixHash
+                        && name.equals(namespacePrefix[i])
+                )) {
+                    final String s = name == null ? "default" : "'" + name + "'";
+                    throw new XmlPullParserException(
+                            "duplicated namespace declaration for " + s + " prefix", this, null);
+                }
+            }
+
+            ++namespaceEnd;
+
+        } else {
+            if (!usePC) {
+                attributeValue[attributeCount] =
+                        new String(buf, posStart, pos - 1 - posStart);
+            } else {
+                attributeValue[attributeCount] =
+                        new String(pc, pcStart, pcEnd - pcStart);
+            }
+            ++attributeCount;
+        }
+        posStart = prevPosStart - bufAbsoluteStart;
+        return ch;
+    }
+
+    protected char[] charRefOneCharBuf = new char[1];
+
+    protected char[] parseEntityRef()
+            throws XmlPullParserException, IOException {
+        // entity reference http://www.w3.org/TR/2000/REC-xml-20001006#NT-Reference
+        // [67] Reference          ::=          EntityRef | CharRef
+
+        // ASSUMPTION just after &
+        entityRefName = null;
+        posStart = pos;
+        char ch = more();
+        if (ch == '#') {
+            // parse character reference
+            char charRef = 0;
+            ch = more();
+            if (ch == 'x') {
+                //encoded in hex
+                while (true) {
+                    ch = more();
+                    if (ch >= '0' && ch <= '9') {
+                        charRef = (char) (charRef * 16 + (ch - '0'));
+                    } else if (ch >= 'a' && ch <= 'f') {
+                        charRef = (char) (charRef * 16 + (ch - ('a' - 10)));
+                    } else if (ch >= 'A' && ch <= 'F') {
+                        charRef = (char) (charRef * 16 + (ch - ('A' - 10)));
+                    } else if (ch == ';') {
+                        break;
+                    } else {
+                        throw new XmlPullParserException(
+                                "character reference (with hex value) may not contain "
+                                        + printable(ch), this, null);
+                    }
+                }
+            } else {
+                // encoded in decimal
+                while (true) {
+                    if (ch >= '0' && ch <= '9') {
+                        charRef = (char) (charRef * 10 + (ch - '0'));
+                    } else if (ch == ';') {
+                        break;
+                    } else {
+                        throw new XmlPullParserException(
+                                "character reference (with decimal value) may not contain "
+                                        + printable(ch), this, null);
+                    }
+                    ch = more();
+                }
+            }
+            posEnd = pos - 1;
+            charRefOneCharBuf[0] = charRef;
+            if (tokenize) {
+                text = newString(charRefOneCharBuf, 0, 1);
+            }
+            return charRefOneCharBuf;
+        } else {
+            // [68]     EntityRef          ::=          '&' Name ';'
+            // scan name until ;
+            if (!isNameStartChar(ch)) {
+                throw new XmlPullParserException(
+                        "entity reference names can not start with character '"
+                                + printable(ch) + "'", this, null);
+            }
+            while (true) {
+                ch = more();
+                if (ch == ';') {
+                    break;
+                }
+                if (!isNameChar(ch)) {
+                    throw new XmlPullParserException(
+                            "entity reference name can not contain character "
+                                    + printable(ch) + "'", this, null);
+                }
+            }
+            posEnd = pos - 1;
+            // determine what name maps to
+            final int len = posEnd - posStart;
+            if (len == 2 && buf[posStart] == 'l' && buf[posStart + 1] == 't') {
+                if (tokenize) {
+                    text = "<";
+                }
+                charRefOneCharBuf[0] = '<';
+                return charRefOneCharBuf;
+                //if(paramPC || isParserTokenizing) {
+                //    if(pcEnd >= pc.length) ensurePC();
+                //   pc[pcEnd++] = '<';
+                //}
+            } else if (len == 3 && buf[posStart] == 'a'
+                    && buf[posStart + 1] == 'm' && buf[posStart + 2] == 'p') {
+                if (tokenize) {
+                    text = "&";
+                }
+                charRefOneCharBuf[0] = '&';
+                return charRefOneCharBuf;
+            } else if (len == 2 && buf[posStart] == 'g' && buf[posStart + 1] == 't') {
+                if (tokenize) {
+                    text = ">";
+                }
+                charRefOneCharBuf[0] = '>';
+                return charRefOneCharBuf;
+            } else if (len == 4 && buf[posStart] == 'a' && buf[posStart + 1] == 'p'
+                    && buf[posStart + 2] == 'o' && buf[posStart + 3] == 's') {
+                if (tokenize) {
+                    text = "'";
+                }
+                charRefOneCharBuf[0] = '\'';
+                return charRefOneCharBuf;
+            } else if (len == 4 && buf[posStart] == 'q' && buf[posStart + 1] == 'u'
+                    && buf[posStart + 2] == 'o' && buf[posStart + 3] == 't') {
+                if (tokenize) {
+                    text = "\"";
+                }
+                charRefOneCharBuf[0] = '"';
+                return charRefOneCharBuf;
+            } else {
+                final char[] result = lookuEntityReplacement(len);
+                if (result != null) {
+                    return result;
+                }
+            }
+            if (tokenize) text = null;
+            return null;
+        }
+    }
+
+    protected char[] lookuEntityReplacement(int entitNameLen)
+            throws XmlPullParserException, IOException {
+        if (!allStringsInterned) {
+            final int hash = fastHash(buf, posStart, posEnd - posStart);
+            LOOP:
+            for (int i = entityEnd - 1; i >= 0; --i) {
+                if (hash == entityNameHash[i] && entitNameLen == entityNameBuf[i].length) {
+                    final char[] entityBuf = entityNameBuf[i];
+                    for (int j = 0; j < entitNameLen; j++) {
+                        if (buf[posStart + j] != entityBuf[j]) continue LOOP;
+                    }
+                    if (tokenize) text = entityReplacement[i];
+                    return entityReplacementBuf[i];
+                }
+            }
+        } else {
+            entityRefName = newString(buf, posStart, posEnd - posStart);
+            for (int i = entityEnd - 1; i >= 0; --i) {
+                // take advantage that interning for newStirng is enforced
+                if (entityRefName == entityName[i]) {
+                    if (tokenize) text = entityReplacement[i];
+                    return entityReplacementBuf[i];
+                }
+            }
+        }
+        return null;
+    }
+
+
+    protected void parseComment()
+            throws XmlPullParserException, IOException {
+        // implements XML 1.0 Section 2.5 Comments
+
+        //ASSUMPTION: seen <!-
+        char ch = more();
+        if (ch != '-') throw new XmlPullParserException(
+                "expected <!-- for comment start", this, null);
+        if (tokenize) posStart = pos;
+
+        final int curLine = lineNumber;
+        final int curColumn = columnNumber;
+        try {
+            final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+            boolean normalizedCR = false;
+
+            boolean seenDash = false;
+            boolean seenDashDash = false;
+            while (true) {
+                // scan until it hits -->
+                ch = more();
+                if (seenDashDash && ch != '>') {
+                    throw new XmlPullParserException(
+                            "in comment after two dashes (--) next character must be >"
+                                    + " not " + printable(ch), this, null);
+                }
+                if (ch == '-') {
+                    if (!seenDash) {
+                        seenDash = true;
+                    } else {
+                        seenDashDash = true;
+                        seenDash = false;
+                    }
+                } else if (ch == '>') {
+                    if (seenDashDash) {
+                        break;  // found end sequence!!!!
+                    } else {
+                        seenDashDash = false;
+                    }
+                    seenDash = false;
+                } else {
+                    seenDash = false;
+                }
+                if (normalizeIgnorableWS) {
+                    if (ch == '\r') {
+                        normalizedCR = true;
+                        //posEnd = pos -1;
+                        //joinPC();
+                        // posEnd is already set
+                        if (!usePC) {
+                            posEnd = pos - 1;
+                            if (posEnd > posStart) {
+                                joinPC();
+                            } else {
+                                usePC = true;
+                                pcStart = pcEnd = 0;
+                            }
+                        }
+                        //assert usePC == true;
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = '\n';
+                    } else if (ch == '\n') {
+                        if (!normalizedCR && usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = '\n';
+                        }
+                        normalizedCR = false;
+                    } else {
+                        if (usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = ch;
+                        }
+                        normalizedCR = false;
+                    }
+                }
+            }
+
+        } catch (EOFException ex) {
+            // detect EOF and create meaningful error ...
+            throw new XmlPullParserException(
+                    "comment started on line " + curLine + " and column " + curColumn + " was not closed",
+                    this, ex);
+        }
+        if (tokenize) {
+            posEnd = pos - 3;
+            if (usePC) {
+                pcEnd -= 2;
+            }
+        }
+    }
+
+    protected boolean parsePI()
+            throws XmlPullParserException, IOException {
+        // implements XML 1.0 Section 2.6 Processing Instructions
+
+        // [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
+        // [17] PITarget         ::=    Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+        //ASSUMPTION: seen <?
+        if (tokenize) posStart = pos;
+        final int curLine = lineNumber;
+        final int curColumn = columnNumber;
+        int piTargetStart = pos + bufAbsoluteStart;
+        int piTargetEnd = -1;
+        final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+        boolean normalizedCR = false;
+
+        try {
+            boolean seenQ = false;
+            char ch = more();
+            if (isS(ch)) {
+                throw new XmlPullParserException(
+                        "processing instruction PITarget must be exactly after <? and not white space character",
+                        this, null);
+            }
+            while (true) {
+                // scan until it hits ?>
+                //ch = more();
+
+                if (ch == '?') {
+                    seenQ = true;
+                } else if (ch == '>') {
+                    if (seenQ) {
+                        break;  // found end sequence!!!!
+                    }
+                    seenQ = false;
+                } else {
+                    if (piTargetEnd == -1 && isS(ch)) {
+                        piTargetEnd = pos - 1 + bufAbsoluteStart;
+
+                        // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
+                        if ((piTargetEnd - piTargetStart) == 3) {
+                            if ((buf[piTargetStart] == 'x' || buf[piTargetStart] == 'X')
+                                    && (buf[piTargetStart + 1] == 'm' || buf[piTargetStart + 1] == 'M')
+                                    && (buf[piTargetStart + 2] == 'l' || buf[piTargetStart + 2] == 'L')
+                            ) {
+                                if (piTargetStart > 3) {  //<?xml is allowed as first characters in input ...
+                                    throw new XmlPullParserException(
+                                            "processing instruction can not have PITarget with reserveld xml name",
+                                            this, null);
+                                } else {
+                                    if (buf[piTargetStart] != 'x'
+                                            && buf[piTargetStart + 1] != 'm'
+                                            && buf[piTargetStart + 2] != 'l') {
+                                        throw new XmlPullParserException(
+                                                "XMLDecl must have xml name in lowercase",
+                                                this, null);
+                                    }
+                                }
+                                parseXmlDecl(ch);
+                                if (tokenize) posEnd = pos - 2;
+                                final int off = piTargetStart - bufAbsoluteStart + 3;
+                                final int len = pos - 2 - off;
+                                xmlDeclContent = newString(buf, off, len);
+                                return false;
+                            }
+                        }
+                    }
+                    seenQ = false;
+                }
+                if (normalizeIgnorableWS) {
+                    if (ch == '\r') {
+                        normalizedCR = true;
+                        //posEnd = pos -1;
+                        //joinPC();
+                        // posEnd is already set
+                        if (!usePC) {
+                            posEnd = pos - 1;
+                            if (posEnd > posStart) {
+                                joinPC();
+                            } else {
+                                usePC = true;
+                                pcStart = pcEnd = 0;
+                            }
+                        }
+                        //assert usePC == true;
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = '\n';
+                    } else if (ch == '\n') {
+                        if (!normalizedCR && usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = '\n';
+                        }
+                        normalizedCR = false;
+                    } else {
+                        if (usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = ch;
+                        }
+                        normalizedCR = false;
+                    }
+                }
+                ch = more();
+            }
+        } catch (EOFException ex) {
+            // detect EOF and create meaningful error ...
+            throw new XmlPullParserException(
+                    "processing instruction started on line " + curLine + " and column " + curColumn
+                            + " was not closed",
+                    this, ex);
+        }
+        if (piTargetEnd == -1) {
+            piTargetEnd = pos - 2 + bufAbsoluteStart;
+            //throw new XmlPullParserException(
+            //    "processing instruction must have PITarget name", this, null);
+        }
+        piTargetStart -= bufAbsoluteStart;
+        piTargetEnd -= bufAbsoluteStart;
+        if (tokenize) {
+            posEnd = pos - 2;
+            if (normalizeIgnorableWS) {
+                --pcEnd;
+            }
+        }
+        return true;
+    }
+
+    //    protected final static char[] VERSION = {'v','e','r','s','i','o','n'};
+    //    protected final static char[] NCODING = {'n','c','o','d','i','n','g'};
+    //    protected final static char[] TANDALONE = {'t','a','n','d','a','l','o','n','e'};
+    //    protected final static char[] YES = {'y','e','s'};
+    //    protected final static char[] NO = {'n','o'};
+
+    protected final static char[] VERSION = "version".toCharArray();
+    protected final static char[] NCODING = "ncoding".toCharArray();
+    protected final static char[] TANDALONE = "tandalone".toCharArray();
+    protected final static char[] YES = "yes".toCharArray();
+    protected final static char[] NO = "no".toCharArray();
+
+
+    protected void parseXmlDecl(char ch)
+            throws XmlPullParserException, IOException {
+        // [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
+
+        // first make sure that relative positions will stay OK
+        preventBufferCompaction = true;
+        bufStart = 0; // necessary to keep pos unchanged during expansion!
+
+        // --- parse VersionInfo
+
+        // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
+        // parse is positioned just on first S past <?xml
+        ch = skipS(ch);
+        ch = requireInput(ch, VERSION);
+        // [25] Eq ::= S? '=' S?
+        ch = skipS(ch);
+        if (ch != '=') {
+            throw new XmlPullParserException(
+                    "expected equals sign (=) after version and not " + printable(ch), this, null);
+        }
+        ch = more();
+        ch = skipS(ch);
+        if (ch != '\'' && ch != '"') {
+            throw new XmlPullParserException(
+                    "expected apostrophe (') or quotation mark (\") after version and not "
+                            + printable(ch), this, null);
+        }
+        final char quotChar = ch;
+        //int versionStart = pos + bufAbsoluteStart;  // required if preventBufferCompaction==false
+        final int versionStart = pos;
+        ch = more();
+        // [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
+        while (ch != quotChar) {
+            if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9')
+                    && ch != '_' && ch != '.' && ch != ':' && ch != '-') {
+                throw new XmlPullParserException(
+                        "<?xml version value expected to be in ([a-zA-Z0-9_.:] | '-')"
+                                + " not " + printable(ch), this, null);
+            }
+            ch = more();
+        }
+        final int versionEnd = pos - 1;
+        parseXmlDeclWithVersion(versionStart, versionEnd);
+        preventBufferCompaction = false; // alow again buffer commpaction - pos MAY chnage
+    }
+    //protected String xmlDeclVersion;
+
+    protected void parseXmlDeclWithVersion(int versionStart, int versionEnd)
+            throws XmlPullParserException, IOException {
+        // check version is "1.0"
+        if ((versionEnd - versionStart != 3)
+                || buf[versionStart] != '1'
+                || buf[versionStart + 1] != '.'
+                || buf[versionStart + 2] != '0') {
+            throw new XmlPullParserException(
+                    "only 1.0 is supported as <?xml version not '"
+                            + printable(new String(buf, versionStart, versionEnd - versionStart)) + "'", this, null);
+        }
+        xmlDeclVersion = newString(buf, versionStart, versionEnd - versionStart);
+
+        // [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
+        char ch = more();
+        ch = skipS(ch);
+        if (ch == 'e') {
+            ch = more();
+            ch = requireInput(ch, NCODING);
+            ch = skipS(ch);
+            if (ch != '=') {
+                throw new XmlPullParserException(
+                        "expected equals sign (=) after encoding and not " + printable(ch), this, null);
+            }
+            ch = more();
+            ch = skipS(ch);
+            if (ch != '\'' && ch != '"') {
+                throw new XmlPullParserException(
+                        "expected apostrophe (') or quotation mark (\") after encoding and not "
+                                + printable(ch), this, null);
+            }
+            final char quotChar = ch;
+            final int encodingStart = pos;
+            ch = more();
+            // [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
+            if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z')) {
+                throw new XmlPullParserException(
+                        "<?xml encoding name expected to start with [A-Za-z]"
+                                + " not " + printable(ch), this, null);
+            }
+            ch = more();
+            while (ch != quotChar) {
+                if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') && (ch < '0' || ch > '9')
+                        && ch != '.' && ch != '_' && ch != '-') {
+                    throw new XmlPullParserException(
+                            "<?xml encoding value expected to be in ([A-Za-z0-9._] | '-')"
+                                    + " not " + printable(ch), this, null);
+                }
+                ch = more();
+            }
+            final int encodingEnd = pos - 1;
+
+            // TODO reconcile with setInput encodingName
+            inputEncoding = newString(buf, encodingStart, encodingEnd - encodingStart);
+            ch = more();
+        }
+
+        ch = skipS(ch);
+        // [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
+        if (ch == 's') {
+            ch = more();
+            ch = requireInput(ch, TANDALONE);
+            ch = skipS(ch);
+            if (ch != '=') {
+                throw new XmlPullParserException(
+                        "expected equals sign (=) after standalone and not " + printable(ch),
+                        this, null);
+            }
+            ch = more();
+            ch = skipS(ch);
+            if (ch != '\'' && ch != '"') {
+                throw new XmlPullParserException(
+                        "expected apostrophe (') or quotation mark (\") after encoding and not "
+                                + printable(ch), this, null);
+            }
+            char quotChar = ch;
+            int standaloneStart = pos;
+            ch = more();
+            if (ch == 'y') {
+                ch = requireInput(ch, YES);
+                //Boolean standalone = new Boolean(true);
+                xmlDeclStandalone = new Boolean(true);
+            } else if (ch == 'n') {
+                ch = requireInput(ch, NO);
+                //Boolean standalone = new Boolean(false);
+                xmlDeclStandalone = new Boolean(false);
+            } else {
+                throw new XmlPullParserException(
+                        "expected 'yes' or 'no' after standalone and not "
+                                + printable(ch), this, null);
+            }
+            if (ch != quotChar) {
+                throw new XmlPullParserException(
+                        "expected " + quotChar + " after standalone value not "
+                                + printable(ch), this, null);
+            }
+            ch = more();
+        }
+
+
+        ch = skipS(ch);
+        if (ch != '?') {
+            throw new XmlPullParserException(
+                    "expected ?> as last part of <?xml not "
+                            + printable(ch), this, null);
+        }
+        ch = more();
+        if (ch != '>') {
+            throw new XmlPullParserException(
+                    "expected ?> as last part of <?xml not "
+                            + printable(ch), this, null);
+        }
+
+// NOTE: this code is broken as for some types of input streams (URLConnection ...)
+// it is not possible to do more than once new InputStreamReader(inputStream)
+// as it somehow detects it and closes undelrying inout stram (b.....d!)
+// In future one will need better low level byte-by-byte reading of prolog and then doing InputStream ...
+// for more details see http://www.extreme.indiana.edu/bugzilla/show_bug.cgi?id=135
+        //        //reset input stream
+//        if ((this.inputEncoding != oldEncoding) && (this.inputStream != null)) {
+//            if ((this.inputEncoding != null) && (!this.inputEncoding.equalsIgnoreCase(oldEncoding))) {
+//                //              //there is need to reparse input to set location OK
+//                //              reset();
+//                this.reader = new InputStreamReader(this.inputStream, this.inputEncoding);
+//                //              //skip <?xml
+//                //              for (int i = 0; i < 5; i++){
+//                //                  ch=more();
+//                //              }
+//                //              parseXmlDecl(ch);
+//            }
+//        }
+    }
+
+    protected void parseDocdecl()
+            throws XmlPullParserException, IOException {
+        //ASSUMPTION: seen <!D
+        char ch = more();
+        if (ch != 'O') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        ch = more();
+        if (ch != 'C') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        ch = more();
+        if (ch != 'T') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        ch = more();
+        if (ch != 'Y') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        ch = more();
+        if (ch != 'P') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        ch = more();
+        if (ch != 'E') throw new XmlPullParserException(
+                "expected <!DOCTYPE", this, null);
+        posStart = pos;
+        // do simple and crude scanning for end of doctype
+
+        // [28]  doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('['
+        //                      (markupdecl | DeclSep)* ']' S?)? '>'
+        int bracketLevel = 0;
+        final boolean normalizeIgnorableWS = tokenize == true && roundtripSupported == false;
+        boolean normalizedCR = false;
+        while (true) {
+            ch = more();
+            if (ch == '[') ++bracketLevel;
+            if (ch == ']') --bracketLevel;
+            if (ch == '>' && bracketLevel == 0) break;
+            if (normalizeIgnorableWS) {
+                if (ch == '\r') {
+                    normalizedCR = true;
+                    //posEnd = pos -1;
+                    //joinPC();
+                    // posEnd is alreadys set
+                    if (!usePC) {
+                        posEnd = pos - 1;
+                        if (posEnd > posStart) {
+                            joinPC();
+                        } else {
+                            usePC = true;
+                            pcStart = pcEnd = 0;
+                        }
+                    }
+                    //assert usePC == true;
+                    if (pcEnd >= pc.length) ensurePC(pcEnd);
+                    pc[pcEnd++] = '\n';
+                } else if (ch == '\n') {
+                    if (!normalizedCR && usePC) {
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = '\n';
+                    }
+                    normalizedCR = false;
+                } else {
+                    if (usePC) {
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = ch;
+                    }
+                    normalizedCR = false;
+                }
+            }
+
+        }
+        posEnd = pos - 1;
+    }
+
+    protected void parseCDSect(boolean hadCharData)
+            throws XmlPullParserException, IOException {
+        // implements XML 1.0 Section 2.7 CDATA Sections
+
+        // [18] CDSect ::= CDStart CData CDEnd
+        // [19] CDStart ::=  '<![CDATA['
+        // [20] CData ::= (Char* - (Char* ']]>' Char*))
+        // [21] CDEnd ::= ']]>'
+
+        //ASSUMPTION: seen <![
+        char ch = more();
+        if (ch != 'C') throw new XmlPullParserException(
+                "expected <[CDATA[ for comment start", this, null);
+        ch = more();
+        if (ch != 'D') throw new XmlPullParserException(
+                "expected <[CDATA[ for comment start", this, null);
+        ch = more();
+        if (ch != 'A') throw new XmlPullParserException(
+                "expected <[CDATA[ for comment start", this, null);
+        ch = more();
+        if (ch != 'T') throw new XmlPullParserException(
+                "expected <[CDATA[ for comment start", this, null);
+        ch = more();
+        if (ch != 'A') throw new XmlPullParserException(
+                "expected <[CDATA[ for comment start", this, null);
+        ch = more();
+        if (ch != '[') throw new XmlPullParserException(
+                "expected <![CDATA[ for comment start", this, null);
+
+        //if(tokenize) {
+        final int cdStart = pos + bufAbsoluteStart;
+        final int curLine = lineNumber;
+        final int curColumn = columnNumber;
+        final boolean normalizeInput = tokenize == false || roundtripSupported == false;
+        try {
+            if (normalizeInput) {
+                if (hadCharData) {
+                    if (!usePC) {
+                        // posEnd is correct already!!!
+                        if (posEnd > posStart) {
+                            joinPC();
+                        } else {
+                            usePC = true;
+                            pcStart = pcEnd = 0;
+                        }
+                    }
+                }
+            }
+            boolean seenBracket = false;
+            boolean seenBracketBracket = false;
+            boolean normalizedCR = false;
+            while (true) {
+                // scan until it hits "]]>"
+                ch = more();
+                if (ch == ']') {
+                    if (!seenBracket) {
+                        seenBracket = true;
+                    } else {
+                        seenBracketBracket = true;
+                        //seenBracket = false;
+                    }
+                } else if (ch == '>') {
+                    if (seenBracket && seenBracketBracket) {
+                        break;  // found end sequence!!!!
+                    } else {
+                        seenBracketBracket = false;
+                    }
+                    seenBracket = false;
+                } else {
+                    if (seenBracket) {
+                        seenBracket = false;
+                    }
+                }
+                if (normalizeInput) {
+                    // deal with normalization issues ...
+                    if (ch == '\r') {
+                        normalizedCR = true;
+                        posStart = cdStart - bufAbsoluteStart;
+                        posEnd = pos - 1; // posEnd is alreadys set
+                        if (!usePC) {
+                            if (posEnd > posStart) {
+                                joinPC();
+                            } else {
+                                usePC = true;
+                                pcStart = pcEnd = 0;
+                            }
+                        }
+                        //assert usePC == true;
+                        if (pcEnd >= pc.length) ensurePC(pcEnd);
+                        pc[pcEnd++] = '\n';
+                    } else if (ch == '\n') {
+                        if (!normalizedCR && usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = '\n';
+                        }
+                        normalizedCR = false;
+                    } else {
+                        if (usePC) {
+                            if (pcEnd >= pc.length) ensurePC(pcEnd);
+                            pc[pcEnd++] = ch;
+                        }
+                        normalizedCR = false;
+                    }
+                }
+            }
+        } catch (EOFException ex) {
+            // detect EOF and create meaningful error ...
+            throw new XmlPullParserException(
+                    "CDATA section started on line " + curLine + " and column " + curColumn + " was not closed",
+                    this, ex);
+        }
+        if (normalizeInput) {
+            if (usePC) {
+                pcEnd = pcEnd - 2;
+            }
+        }
+        posStart = cdStart - bufAbsoluteStart;
+        posEnd = pos - 3;
+    }
+
+    protected void fillBuf() throws IOException, XmlPullParserException {
+        if (reader == null) throw new XmlPullParserException(
+                "reader must be set before parsing is started");
+
+        // see if we are in compaction area
+        if (bufEnd > bufSoftLimit) {
+
+            // expand buffer it makes sense!!!!
+            boolean compact = bufStart > bufSoftLimit;
+            boolean expand = false;
+            if (preventBufferCompaction) {
+                compact = false;
+                expand = true;
+            } else if (!compact) {
+                //freeSpace
+                if (bufStart < buf.length / 2) {
+                    // less then half buffer available forcompactin --> expand instead!!!
+                    expand = true;
+                } else {
+                    // at least half of buffer can be reclaimed --> worthwhile effort!!!
+                    compact = true;
+                }
+            }
+
+            // if buffer almost full then compact it
+            if (compact) {
+                //TODO: look on trashing
+                // //assert bufStart > 0
+                System.arraycopy(buf, bufStart, buf, 0, bufEnd - bufStart);
+                if (TRACE_SIZING) System.out.println(
+                        "TRACE_SIZING fillBuf() compacting " + bufStart
+                                + " bufEnd=" + bufEnd
+                                + " pos=" + pos + " posStart=" + posStart + " posEnd=" + posEnd
+                                + " buf first 100 chars:" + new String(buf, bufStart,
+                                bufEnd - bufStart < 100 ? bufEnd - bufStart : 100));
+
+            } else if (expand) {
+                final int newSize = 2 * buf.length;
+                final char newBuf[] = new char[newSize];
+                if (TRACE_SIZING) System.out.println("TRACE_SIZING fillBuf() " + buf.length + " => " + newSize);
+                System.arraycopy(buf, bufStart, newBuf, 0, bufEnd - bufStart);
+                buf = newBuf;
+                if (bufLoadFactor > 0) {
+                    //bufSoftLimit = ( bufLoadFactor * buf.length ) /100;
+                    bufSoftLimit = (int) ((((long) bufLoadFactor) * buf.length) / 100);
+                }
+
+            } else {
+                throw new XmlPullParserException("internal error in fillBuffer()");
+            }
+            bufEnd -= bufStart;
+            pos -= bufStart;
+            posStart -= bufStart;
+            posEnd -= bufStart;
+            bufAbsoluteStart += bufStart;
+            bufStart = 0;
+            if (TRACE_SIZING) System.out.println(
+                    "TRACE_SIZING fillBuf() after bufEnd=" + bufEnd
+                            + " pos=" + pos + " posStart=" + posStart + " posEnd=" + posEnd
+                            + " buf first 100 chars:" + new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
+        }
+        // at least one character must be read or error
+        final int len = buf.length - bufEnd > READ_CHUNK_SIZE ? READ_CHUNK_SIZE : buf.length - bufEnd;
+        final int ret = reader.read(buf, bufEnd, len);
+        if (ret > 0) {
+            bufEnd += ret;
+            if (TRACE_SIZING) System.out.println(
+                    "TRACE_SIZING fillBuf() after filling in buffer"
+                            + " buf first 100 chars:" + new String(buf, 0, bufEnd < 100 ? bufEnd : 100));
+
+            return;
+        }
+        if (ret == -1) {
+            if (bufAbsoluteStart == 0 && pos == 0) {
+                throw new EOFException("input contained no data");
+            } else {
+                if (seenRoot && depth == 0) { // inside parsing epilog!!!
+                    reachedEnd = true;
+                    return;
+                } else {
+                    StringBuffer expectedTagStack = new StringBuffer();
+                    if (depth > 0) {
+                        //final char[] cbuf = elRawName[depth];
+                        //final String startname = new String(cbuf, 0, elRawNameEnd[depth]);
+                        expectedTagStack.append(" - expected end tag");
+                        if (depth > 1) {
+                            expectedTagStack.append("s"); //more than one end tag
+                        }
+                        expectedTagStack.append(" ");
+                        for (int i = depth; i > 0; i--) {
+                            String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
+                            expectedTagStack.append("</").append(tagName).append('>');
+                        }
+                        expectedTagStack.append(" to close");
+                        for (int i = depth; i > 0; i--) {
+                            if (i != depth) {
+                                expectedTagStack.append(" and"); //more than one end tag
+                            }
+                            String tagName = new String(elRawName[i], 0, elRawNameEnd[i]);
+                            expectedTagStack.append(" start tag <" + tagName + ">");
+                            expectedTagStack.append(" from line " + elRawNameLine[i]);
+                        }
+                        expectedTagStack.append(", parser stopped on");
+                    }
+                    throw new EOFException("no more data available"
+                            + expectedTagStack.toString() + getPositionDescription());
+                }
+            }
+        } else {
+            throw new IOException("error reading input, returned " + ret);
+        }
+    }
+
+    protected char more() throws IOException, XmlPullParserException {
+        if (pos >= bufEnd) {
+            fillBuf();
+            // this return value should be ignonored as it is used in epilog parsing ...
+            if (reachedEnd) return (char) -1;
+        }
+        final char ch = buf[pos++];
+        //line/columnNumber
+        if (ch == '\n') {
+            ++lineNumber;
+            columnNumber = 1;
+        } else {
+            ++columnNumber;
+        }
+        //System.out.print(ch);
+        return ch;
+    }
+
+    //    /**
+    //     * This function returns position of parser in XML input stream
+    //     * (how many <b>characters</b> were processed.
+    //     * <p><b>NOTE:</b> this logical position and not byte offset as encodings
+    //     * such as UTF8 may use more than one byte to encode one character.
+    //     */
+    //    public int getCurrentInputPosition() {
+    //        return pos + bufAbsoluteStart;
+    //    }
+
+    protected void ensurePC(int end) {
+        //assert end >= pc.length;
+        final int newSize = end > READ_CHUNK_SIZE ? 2 * end : 2 * READ_CHUNK_SIZE;
+        final char[] newPC = new char[newSize];
+        if (TRACE_SIZING)
+            System.out.println("TRACE_SIZING ensurePC() " + pc.length + " ==> " + newSize + " end=" + end);
+        System.arraycopy(pc, 0, newPC, 0, pcEnd);
+        pc = newPC;
+        //assert end < pc.length;
+    }
+
+    protected void joinPC() {
+        //assert usePC == false;
+        //assert posEnd > posStart;
+        final int len = posEnd - posStart;
+        final int newEnd = pcEnd + len + 1;
+        if (newEnd >= pc.length) ensurePC(newEnd); // add 1 for extra space for one char
+        //assert newEnd < pc.length;
+        System.arraycopy(buf, posStart, pc, pcEnd, len);
+        pcEnd += len;
+        usePC = true;
+
+    }
+
+    protected char requireInput(char ch, char[] input)
+            throws XmlPullParserException, IOException {
+        for (int i = 0; i < input.length; i++) {
+            if (ch != input[i]) {
+                throw new XmlPullParserException(
+                        "expected " + printable(input[i]) + " in " + new String(input)
+                                + " and not " + printable(ch), this, null);
+            }
+            ch = more();
+        }
+        return ch;
+    }
+
+    protected char requireNextS()
+            throws XmlPullParserException, IOException {
+        final char ch = more();
+        if (!isS(ch)) {
+            throw new XmlPullParserException(
+                    "white space is required and not " + printable(ch), this, null);
+        }
+        return skipS(ch);
+    }
+
+    protected char skipS(char ch)
+            throws XmlPullParserException, IOException {
+        while (isS(ch)) {
+            ch = more();
+        } // skip additional spaces
+        return ch;
+    }
+
+    // nameStart / name lookup tables based on XML 1.1 http://www.w3.org/TR/2001/WD-xml11-20011213/
+    protected static final int LOOKUP_MAX = 0x400;
+    protected static final char LOOKUP_MAX_CHAR = (char) LOOKUP_MAX;
+    //    protected static int lookupNameStartChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
+    //    protected static int lookupNameChar[] = new int[ LOOKUP_MAX_CHAR / 32 ];
+    protected static boolean lookupNameStartChar[] = new boolean[LOOKUP_MAX];
+    protected static boolean lookupNameChar[] = new boolean[LOOKUP_MAX];
+
+    private static final void setName(char ch)
+    //{ lookupNameChar[ (int)ch / 32 ] |= (1 << (ch % 32)); }
+    {
+        lookupNameChar[ch] = true;
+    }
+
+    private static final void setNameStart(char ch)
+    //{ lookupNameStartChar[ (int)ch / 32 ] |= (1 << (ch % 32)); setName(ch); }
+    {
+        lookupNameStartChar[ch] = true;
+        setName(ch);
+    }
+
+    static {
+        setNameStart(':');
+        for (char ch = 'A'; ch <= 'Z'; ++ch) setNameStart(ch);
+        setNameStart('_');
+        for (char ch = 'a'; ch <= 'z'; ++ch) setNameStart(ch);
+        for (char ch = '\u00c0'; ch <= '\u02FF'; ++ch) setNameStart(ch);
+        for (char ch = '\u0370'; ch <= '\u037d'; ++ch) setNameStart(ch);
+        for (char ch = '\u037f'; ch < '\u0400'; ++ch) setNameStart(ch);
+
+        setName('-');
+        setName('.');
+        for (char ch = '0'; ch <= '9'; ++ch) setName(ch);
+        setName('\u00b7');
+        for (char ch = '\u0300'; ch <= '\u036f'; ++ch) setName(ch);
+    }
+
+    //private final static boolean isNameStartChar(char ch) {
+    protected boolean isNameStartChar(char ch) {
+        return (ch < LOOKUP_MAX_CHAR && lookupNameStartChar[ch])
+                || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
+                || (ch >= '\u202A' && ch <= '\u218F')
+                || (ch >= '\u2800' && ch <= '\uFFEF')
+                ;
+
+        //      if(ch < LOOKUP_MAX_CHAR) return lookupNameStartChar[ ch ];
+        //      else return ch <= '\u2027'
+        //              || (ch >= '\u202A' &&  ch <= '\u218F')
+        //              || (ch >= '\u2800' &&  ch <= '\uFFEF')
+        //              ;
+        //return false;
+        //        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
+        //          || (ch >= '0' && ch <= '9');
+        //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+        //        if(ch <= '\u2027') return true;
+        //        //[#x202A-#x218F]
+        //        if(ch < '\u202A') return false;
+        //        if(ch <= '\u218F') return true;
+        //        // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
+        //        if(ch < '\u2800') return false;
+        //        if(ch <= '\uFFEF') return true;
+        //        return false;
+
+
+        // else return (supportXml11 && ( (ch < '\u2027') || (ch > '\u2029' && ch < '\u2200') ...
+    }
+
+    //private final static boolean isNameChar(char ch) {
+    protected boolean isNameChar(char ch) {
+        //return isNameStartChar(ch);
+
+        //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+
+        return (ch < LOOKUP_MAX_CHAR && lookupNameChar[ch])
+                || (ch >= LOOKUP_MAX_CHAR && ch <= '\u2027')
+                || (ch >= '\u202A' && ch <= '\u218F')
+                || (ch >= '\u2800' && ch <= '\uFFEF')
+                ;
+        //return false;
+        //        return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == ':'
+        //          || (ch >= '0' && ch <= '9');
+        //        if(ch < LOOKUP_MAX_CHAR) return (lookupNameStartChar[ (int)ch / 32 ] & (1 << (ch % 32))) != 0;
+
+        //else return
+        //  else if(ch <= '\u2027') return true;
+        //        //[#x202A-#x218F]
+        //        else if(ch < '\u202A') return false;
+        //        else if(ch <= '\u218F') return true;
+        //        // added pairts [#x2800-#xD7FF] | [#xE000-#xFDCF] | [#xFDE0-#xFFEF] | [#x10000-#x10FFFF]
+        //        else if(ch < '\u2800') return false;
+        //        else if(ch <= '\uFFEF') return true;
+        //else return false;
+    }
+
+    protected boolean isS(char ch) {
+        return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
+        // || (supportXml11 && (ch == '\u0085' || ch == '\u2028');
+    }
+
+    //protected boolean isChar(char ch) { return (ch < '\uD800' || ch > '\uDFFF')
+    //  ch != '\u0000' ch < '\uFFFE'
+
+
+    //protected char printable(char ch) { return ch; }
+    protected String printable(char ch) {
+        if (ch == '\n') {
+            return "\\n";
+        } else if (ch == '\r') {
+            return "\\r";
+        } else if (ch == '\t') {
+            return "\\t";
+        } else if (ch == '\'') {
+            return "\\'";
+        }
+        if (ch > 127 || ch < 32) {
+            return "\\u" + Integer.toHexString((int) ch);
+        }
+        return "" + ch;
+    }
+
+    protected String printable(String s) {
+        if (s == null) return null;
+        final int sLen = s.length();
+        StringBuffer buf = new StringBuffer(sLen + 10);
+        for (int i = 0; i < sLen; ++i) {
+            buf.append(printable(s.charAt(i)));
+        }
+        s = buf.toString();
+        return s;
+    }
+}
+
+
+/*
+ * Indiana University Extreme! Lab Software License, Version 1.2
+ *
+ * Copyright (C) 2003 The Trustees of Indiana University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1) All redistributions of source code must retain the above
+ *    copyright notice, the list of authors in the original source
+ *    code, this list of conditions and the disclaimer listed in this
+ *    license;
+ *
+ * 2) All redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the disclaimer
+ *    listed in this license in the documentation and/or other
+ *    materials provided with the distribution;
+ *
+ * 3) Any documentation included with all redistributions must include
+ *    the following acknowledgement:
+ *
+ *      "This product includes software developed by the Indiana
+ *      University Extreme! Lab.  For further information please visit
+ *      http://www.extreme.indiana.edu/"
+ *
+ *    Alternatively, this acknowledgment may appear in the software
+ *    itself, and wherever such third-party acknowledgments normally
+ *    appear.
+ *
+ * 4) The name "Indiana University" or "Indiana University
+ *    Extreme! Lab" shall not be used to endorse or promote
+ *    products derived from this software without prior written
+ *    permission from Indiana University.  For written permission,
+ *    please contact http://www.extreme.indiana.edu/.
+ *
+ * 5) Products derived from this software may not use "Indiana
+ *    University" name nor may "Indiana University" appear in their name,
+ *    without prior written permission of the Indiana University.
+ *
+ * Indiana University provides no reassurances that the source code
+ * provided does not infringe the patent or any other intellectual
+ * property rights of any other entity.  Indiana University disclaims any
+ * liability to any recipient for claims brought by any other entity
+ * based on infringement of intellectual property rights or otherwise.
+ *
+ * LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH
+ * NO WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA
+ * UNIVERSITY GIVES NO WARRANTIES AND MAKES NO REPRESENTATION THAT
+ * SOFTWARE IS FREE OF INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR
+ * OTHER PROPRIETARY RIGHTS.  INDIANA UNIVERSITY MAKES NO WARRANTIES THAT
+ * SOFTWARE IS FREE FROM "BUGS", "VIRUSES", "TROJAN HORSES", "TRAP
+ * DOORS", "WORMS", OR OTHER HARMFUL CODE.  LICENSEE ASSUMES THE ENTIRE
+ * RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR ASSOCIATED MATERIALS,
+ * AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION GENERATED USING
+ * SOFTWARE.
+ */
+
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java
new file mode 100644
index 0000000..f31a090
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParser.java
@@ -0,0 +1,964 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.apache.camel.xml.io;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * XML Pull Parser is an interface that defines parsing functionality provided in
+ * <a href="http://www.xmlpull.org/">XMLPULL V1 API</a> (visit this website to learn more about API and its
+ * implementations).
+ * <p>
+ * There are following different kinds of parser depending on which features are set:
+ * <ul>
+ * <li><b>non-validating</b> parser as defined in XML 1.0 spec when FEATURE_PROCESS_DOCDECL is set to true
+ * <li><b>validating parser</b> as defined in XML 1.0 spec when FEATURE_VALIDATION is true (and that implies that
+ * FEATURE_PROCESS_DOCDECL is true)
+ * <li>when FEATURE_PROCESS_DOCDECL is false (this is default and if different value is required necessary must be
+ * changed before parsing is started) then parser behaves like XML 1.0 compliant non-validating parser under condition
+ * that <em>no DOCDECL is present</em> in XML documents (internal entities can still be defined with
+ * defineEntityReplacementText()). This mode of operation is intended <b>for operation in constrained environments</b>
+ * such as J2ME.
+ * </ul>
+ * <p>
+ * There are two key methods: next() and nextToken(). While next() provides access to high level parsing events,
+ * nextToken() allows access to lower level tokens.
+ * <p>
+ * The current event state of the parser can be determined by calling the <a href="#getEventType()">getEventType()</a>
+ * method. Initially, the parser is in the <a href="#START_DOCUMENT">START_DOCUMENT</a> state.
+ * <p>
+ * The method <a href="#next()">next()</a> advances the parser to the next event. The int value returned from next
+ * determines the current parser state and is identical to the value returned from following calls to getEventType ().
+ * <p>
+ * The following event types are seen by next()
+ * <dl>
+ * <dt><a href="#START_TAG">START_TAG</a>
+ * <dd>An XML start tag was read.
+ * <dt><a href="#TEXT">TEXT</a>
+ * <dd>Text content was read; the text content can be retrieved using the getText() method. (when in validating mode
+ * next() will not report ignorable whitespaces, use nextToken() instead)
+ * <dt><a href="#END_TAG">END_TAG</a>
+ * <dd>An end tag was read
+ * <dt><a href="#END_DOCUMENT">END_DOCUMENT</a>
+ * <dd>No more events are available
+ * </dl>
+ * <p>
+ * after first next() or nextToken() (or any other next*() method) is called user application can obtain XML version,
+ * standalone and encoding from XML declaration in following ways:
+ * <ul>
+ * <li><b>version</b>: getProperty(&quot;<a href=
+ * "http://xmlpull.org/v1/doc/properties.html#xmldecl-version">http://xmlpull.org/v1/doc/properties.html#xmldecl-version</a>&quot;)
+ * returns String ("1.0") or null if XMLDecl was not read or if property is not supported
+ * <li><b>standalone</b>: getProperty(&quot;<a href=
+ * "http://xmlpull.org/v1/doc/features.html#xmldecl-standalone">http://xmlpull.org/v1/doc/features.html#xmldecl-standalone</a>&quot;)
+ * returns Boolean: null if there was no standalone declaration or if property is not supported otherwise returns
+ * Boolean(true) if standalone="yes" and Boolean(false) when standalone="no"
+ * <li><b>encoding</b>: obtained from getInputEncoding() null if stream had unknown encoding (not set in setInputStream)
+ * and it was not declared in XMLDecl
+ * </ul>
+ * A minimal example for using this API may look as follows:
+ *
+ * <pre>
+ * import java.io.IOException;
+ * import java.io.StringReader;
+ *
+ * import org.xmlpull.v1.XmlPullParser;
+ * import org.xmlpull.v1.XmlPullParserException;
+ * import org.xmlpull.v1.XmlPullParserFactory;
+ *
+ * public class SimpleXmlPullApp
+ * {
+ *
+ *     public static void main (String args[])
+ *         throws XmlPullParserException, IOException
+ *     {
+ *         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ *         factory.setNamespaceAware(true);
+ *         XmlPullParser xpp = factory.newPullParser();
+ *
+ *         xpp.setInput( new StringReader ( "&lt;foo%gt;Hello World!&lt;/foo&gt;" ) );
+ *         int eventType = xpp.getEventType();
+ *         while (eventType != xpp.END_DOCUMENT) {
+ *          if(eventType == xpp.START_DOCUMENT) {
+ *              System.out.println("Start document");
+ *          } else if(eventType == xpp.END_DOCUMENT) {
+ *              System.out.println("End document");
+ *          } else if(eventType == xpp.START_TAG) {
+ *              System.out.println("Start tag "+xpp.getName());
+ *          } else if(eventType == xpp.END_TAG) {
+ *              System.out.println("End tag "+xpp.getName());
+ *          } else if(eventType == xpp.TEXT) {
+ *              System.out.println("Text "+xpp.getText());
+ *          }
+ *          eventType = xpp.next();
+ *         }
+ *     }
+ * }
+ * </pre>
+ * <p>
+ * The above example will generate the following output:
+ *
+ * <pre>
+ * Start document
+ * Start tag foo
+ * Text Hello World!
+ * End tag foo
+ * </pre>
+ *
+ * For more details on API usage, please refer to the quick Introduction available at
+ * <a href="http://www.xmlpull.org">http://www.xmlpull.org</a>
+ *
+ * @see #defineEntityReplacementText
+ * @see #getName
+ * @see #getNamespace
+ * @see #getText
+ * @see #next
+ * @see #nextToken
+ * @see #setInput
+ * @see #FEATURE_PROCESS_DOCDECL
+ * @see #FEATURE_VALIDATION
+ * @see #START_DOCUMENT
+ * @see #START_TAG
+ * @see #TEXT
+ * @see #END_TAG
+ * @see #END_DOCUMENT
+ * @author <a href="http://www-ai.cs.uni-dortmund.de/PERSONAL/haustein.html">Stefan Haustein</a>
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+
+public interface XmlPullParser
+{
+
+    /** This constant represents the default namespace (empty string "") */
+    String NO_NAMESPACE = "";
+
+    // ----------------------------------------------------------------------------
+    // EVENT TYPES as reported by next()
+
+    /**
+     * Signalize that parser is at the very beginning of the document and nothing was read yet. This event type can only
+     * be observed by calling getEvent() before the first call to next(), nextToken, or nextTag()).
+     *
+     * @see #next
+     * @see #nextToken
+     */
+    int START_DOCUMENT = 0;
+
+    /**
+     * Logical end of the xml document. Returned from getEventType, next() and nextToken() when the end of the input
+     * document has been reached.
+     * <p>
+     * <strong>NOTE:</strong> calling again <a href="#next()">next()</a> or <a href="#nextToken()">nextToken()</a> will
+     * result in exception being thrown.
+     *
+     * @see #next
+     * @see #nextToken
+     */
+    int END_DOCUMENT = 1;
+
+    /**
+     * Returned from getEventType(), <a href="#next()">next()</a>, <a href="#nextToken()">nextToken()</a> when a start
+     * tag was read. The name of start tag is available from getName(), its namespace and prefix are available from
+     * getNamespace() and getPrefix() if <a href='#FEATURE_PROCESS_NAMESPACES'>namespaces are enabled</a>. See
+     * getAttribute* methods to retrieve element attributes. See getNamespace* methods to retrieve newly declared
+     * namespaces.
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getName
+     * @see #getPrefix
+     * @see #getNamespace
+     * @see #getAttributeCount
+     * @see #getDepth
+     * @see #getNamespaceCount
+     * @see #getNamespace
+     * @see #FEATURE_PROCESS_NAMESPACES
+     */
+    int START_TAG = 2;
+
+    /**
+     * Returned from getEventType(), <a href="#next()">next()</a>, or <a href="#nextToken()">nextToken()</a> when an end
+     * tag was read. The name of start tag is available from getName(), its namespace and prefix are available from
+     * getNamespace() and getPrefix().
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getName
+     * @see #getPrefix
+     * @see #getNamespace
+     * @see #FEATURE_PROCESS_NAMESPACES
+     */
+    int END_TAG = 3;
+
+    /**
+     * Character data was read and will is available by calling getText().
+     * <p>
+     * <strong>Please note:</strong> <a href="#next()">next()</a> will accumulate multiple events into one TEXT event,
+     * skipping IGNORABLE_WHITESPACE, PROCESSING_INSTRUCTION and COMMENT events, In contrast,
+     * <a href="#nextToken()">nextToken()</a> will stop reading text when any other event is observed. Also, when the
+     * state was reached by calling next(), the text value will be normalized, whereas getText() will return
+     * unnormalized content in the case of nextToken(). This allows an exact roundtrip without changing line ends when
+     * examining low level events, whereas for high level applications the text is normalized appropriately.
+     *
+     * @see #next
+     * @see #nextToken
+     * @see #getText
+     */
+    int TEXT = 4;
+
+    // ----------------------------------------------------------------------------
+    // additional events exposed by lower level nextToken()
+
+    /**
+     * A CDATA sections was just read; this token is available only from calls to
+     * <a href="#nextToken()">nextToken()</a>. A call to next() will accumulate various text events into a single event
+     * of type TEXT. The text contained in the CDATA section is available by calling getText().
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int CDSECT = 5;
+
+    /**
+     * An entity reference was just read; this token is available from <a href="#nextToken()">nextToken()</a> only. The
+     * entity name is available by calling getName(). If available, the replacement text can be obtained by calling
+     * getTextt(); otherwise, the user is responsible for resolving the entity reference. This event type is never
+     * returned from next(); next() will accumulate the replacement text and other text events to a single TEXT event.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int ENTITY_REF = 6;
+
+    /**
+     * Ignorable whitespace was just read. This token is available only from <a href="#nextToken()">nextToken()</a>).
+     * For non-validating parsers, this event is only reported by nextToken() when outside the root element. Validating
+     * parsers may be able to detect ignorable whitespace at other locations. The ignorable whitespace string is
+     * available by calling getText()
+     * <p>
+     * <strong>NOTE:</strong> this is different from calling the isWhitespace() method, since text content may be
+     * whitespace but not ignorable. Ignorable whitespace is skipped by next() automatically; this event type is never
+     * returned from next().
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int IGNORABLE_WHITESPACE = 7;
+
+    /**
+     * An XML processing instruction declaration was just read. This event type is available only via
+     * <a href="#nextToken()">nextToken()</a>. getText() will return text that is inside the processing instruction.
+     * Calls to next() will skip processing instructions automatically.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int PROCESSING_INSTRUCTION = 8;
+
+    /**
+     * An XML comment was just read. This event type is this token is available via
+     * <a href="#nextToken()">nextToken()</a> only; calls to next() will skip comments automatically. The content of the
+     * comment can be accessed using the getText() method.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int COMMENT = 9;
+
+    /**
+     * An XML document type declaration was just read. This token is available from
+     * <a href="#nextToken()">nextToken()</a> only. The unparsed text inside the doctype is available via the getText()
+     * method.
+     *
+     * @see #nextToken
+     * @see #getText
+     */
+    int DOCDECL = 10;
+
+    /**
+     * This array can be used to convert the event type integer constants such as START_TAG or TEXT to to a string. For
+     * example, the value of TYPES[START_TAG] is the string "START_TAG". This array is intended for diagnostic output
+     * only. Relying on the contents of the array may be dangerous since malicious applications may alter the array,
+     * although it is final, due to limitations of the Java language.
+     */
+    String[] TYPES = { "START_DOCUMENT", "END_DOCUMENT", "START_TAG", "END_TAG", "TEXT", "CDSECT", "ENTITY_REF",
+            "IGNORABLE_WHITESPACE", "PROCESSING_INSTRUCTION", "COMMENT", "DOCDECL" };
+
+    // ----------------------------------------------------------------------------
+    // namespace related features
+
+    /**
+     * This feature determines whether the parser processes namespaces. As for all features, the default value is false.
+     * <p>
+     * <strong>NOTE:</strong> The value can not be changed during parsing an must be set before parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_PROCESS_NAMESPACES = "http://xmlpull.org/v1/doc/features.html#process-namespaces";
+
+    /**
+     * This feature determines whether namespace attributes are exposed via the attribute access methods. Like all
+     * features, the default value is false. This feature cannot be changed during parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+
+    /**
+     * This feature determines whether the document declaration is processed. If set to false, the DOCDECL event type is
+     * reported by nextToken() and ignored by next(). If this feature is activated, then the document declaration must
+     * be processed by the parser.
+     * <p>
+     * <strong>Please note:</strong> If the document type declaration was ignored, entity references may cause
+     * exceptions later in the parsing process. The default value of this feature is false. It cannot be changed during
+     * parsing.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_PROCESS_DOCDECL = "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+
+    /**
+     * If this feature is activated, all validation errors as defined in the XML 1.0 specification are reported. This
+     * implies that FEATURE_PROCESS_DOCDECL is true and both, the internal and external document type declaration will
+     * be processed.
+     * <p>
+     * <strong>Please Note:</strong> This feature can not be changed during parsing. The default value is false.
+     *
+     * @see #getFeature
+     * @see #setFeature
+     */
+    String FEATURE_VALIDATION = "http://xmlpull.org/v1/doc/features.html#validation";
+
+    /**
+     * Use this call to change the general behaviour of the parser, such as namespace processing or doctype declaration
+     * handling. This method must be called before the first call to next or nextToken. Otherwise, an exception is
+     * thrown.
+     * <p>
+     * Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order to switch on namespace processing. The
+     * initial settings correspond to the properties requested from the XML Pull Parser factory. If none were requested,
+     * all features are deactivated by default.
+     *
+     * @exception XmlPullParserException If the feature is not supported or can not be set
+     * @exception IllegalArgumentException If string with the feature name is null
+     */
+    void setFeature( String name, boolean state )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the current value of the given feature.
+     * <p>
+     * <strong>Please note:</strong> unknown features are <strong>always</strong> returned as false.
+     *
+     * @param name The name of feature to be retrieved.
+     * @return The value of the feature.
+     * @exception IllegalArgumentException if string the feature name is null
+     */
+
+    boolean getFeature( String name );
+
+    /**
+     * Set the value of a property. The property name is any fully-qualified URI.
+     *
+     * @exception XmlPullParserException If the property is not supported or can not be set
+     * @exception IllegalArgumentException If string with the property name is null
+     */
+    void setProperty( String name, Object value )
+            throws XmlPullParserException;
+
+    /**
+     * Look up the value of a property. The property name is any fully-qualified URI.
+     * <p>
+     * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null.
+     *
+     * @param name The name of property to be retrieved.
+     * @return The value of named property.
+     */
+    Object getProperty( String name );
+
+    /**
+     * Set the input source for parser to the given reader and resets the parser. The event type is set to the initial
+     * value START_DOCUMENT. Setting the reader to null will just stop parsing and reset parser state, allowing the
+     * parser to free internal resources such as parsing buffers.
+     */
+    void setInput( Reader in )
+            throws XmlPullParserException;
+
+    /**
+     * Sets the input stream the parser is going to process. This call resets the parser state and sets the event type
+     * to the initial value START_DOCUMENT.
+     * <p>
+     * <strong>NOTE:</strong> If an input encoding string is passed, it MUST be used. Otherwise, if inputEncoding is
+     * null, the parser SHOULD try to determine input encoding following XML 1.0 specification (see below). If encoding
+     * detection is supported then following feature <a href=
+     * "http://xmlpull.org/v1/doc/features.html#detect-encoding">http://xmlpull.org/v1/doc/features.html#detect-encoding</a>
+     * MUST be true and otherwise it must be false
+     *
+     * @param inputStream contains a raw byte input stream of possibly unknown encoding (when inputEncoding is null).
+     * @param inputEncoding if not null it MUST be used as encoding for inputStream
+     */
+    void setInput( InputStream inputStream, String inputEncoding )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the input encoding if known, null otherwise. If setInput(InputStream, inputEncoding) was called with an
+     * inputEncoding value other than null, this value must be returned from this method. Otherwise, if inputEncoding is
+     * null and the parser supports the encoding detection feature
+     * (http://xmlpull.org/v1/doc/features.html#detect-encoding), it must return the detected encoding. If
+     * setInput(Reader) was called, null is returned. After first call to next if XML declaration was present this
+     * method will return encoding declared.
+     */
+    String getInputEncoding();
+
+    /**
+     * Set new value for entity replacement text as defined in
+     * <a href="http://www.w3.org/TR/REC-xml#intern-replacement">XML 1.0 Section 4.5 Construction of Internal Entity
+     * Replacement Text</a>. If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this function will result
+     * in an exception -- when processing of DOCDECL is enabled, there is no need to the entity replacement text
+     * manually.
+     * <p>
+     * The motivation for this function is to allow very small implementations of XMLPULL that will work in J2ME
+     * environments. Though these implementations may not be able to process the document type declaration, they still
+     * can work with known DTDs by using this function.
+     * <p>
+     * <b>Please notes:</b> The given value is used literally as replacement text and it corresponds to declaring entity
+     * in DTD that has all special characters escaped: left angle bracket is replaced with &amp;lt;, ampersand with
+     * &amp;amp; and so on.
+     * <p>
+     * <b>Note:</b> The given value is the literal replacement text and must not contain any other entity reference (if
+     * it contains any entity reference there will be no further replacement).
+     * <p>
+     * <b>Note:</b> The list of pre-defined entity names will always contain standard XML entities such as amp
+     * (&amp;amp;), lt (&amp;lt;), gt (&amp;gt;), quot (&amp;quot;), and apos (&amp;apos;). Those cannot be redefined by
+     * this method!
+     *
+     * @see #setInput
+     * @see #FEATURE_PROCESS_DOCDECL
+     * @see #FEATURE_VALIDATION
+     */
+    void defineEntityReplacementText( String entityName, String replacementText )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the numbers of elements in the namespace stack for the given depth. If namespaces are not enabled, 0 is
+     * returned.
+     * <p>
+     * <b>NOTE:</b> when parser is on END_TAG then it is allowed to call this function with getDepth()+1 argument to
+     * retrieve position of namespace prefixes and URIs that were declared on corresponding START_TAG.
+     * <p>
+     * <b>NOTE:</b> to retrieve lsit of namespaces declared in current element:
+     *
+     * <pre>
+     *       XmlPullParser pp = ...
+     *       int nsStart = pp.getNamespaceCount(pp.getDepth()-1);
+     *       int nsEnd = pp.getNamespaceCount(pp.getDepth());
+     *       for (int i = nsStart; i &gt; nsEnd; i++) {
+     *          String prefix = pp.getNamespacePrefix(i);
+     *          String ns = pp.getNamespaceUri(i);
+     *           // ...
+     *      }
+     * </pre>
+     *
+     * @see #getNamespacePrefix
+     * @see #getNamespaceUri
+     * @see #getNamespace()
+     * @see #getNamespace(String)
+     */
+    int getNamespaceCount( int depth )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the namespace prefix for the given position in the namespace stack. Default namespace declaration
+     * (xmlns='...') will have null as prefix. If the given index is out of range, an exception is thrown.
+     * <p>
+     * <b>Please note:</b> when the parser is on an END_TAG, namespace prefixes that were declared in the corresponding
+     * START_TAG are still accessible although they are no longer in scope.
+     */
+    String getNamespacePrefix( int pos )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the namespace URI for the given position in the namespace stack If the position is out of range, an
+     * exception is thrown.
+     * <p>
+     * <b>NOTE:</b> when parser is on END_TAG then namespace prefixes that were declared in corresponding START_TAG are
+     * still accessible even though they are not in scope
+     */
+    String getNamespaceUri( int pos )
+            throws XmlPullParserException;
+
+    /**
+     * Returns the URI corresponding to the given prefix, depending on current state of the parser.
+     * <p>
+     * If the prefix was not declared in the current scope, null is returned. The default namespace is included in the
+     * namespace table and is available via getNamespace (null).
+     * <p>
+     * This method is a convenience method for
+     *
+     * <pre>
+     * for ( int i = getNamespaceCount( getDepth() ) - 1; i &gt;= 0; i-- )
+     * {
+     *     if ( getNamespacePrefix( i ).equals( prefix ) )
+     *     {
+     *         return getNamespaceUri( i );
+     *     }
+     * }
+     * return null;
+     * </pre>
+     * <p>
+     * <strong>Please note:</strong> parser implementations may provide more efficient lookup, e.g. using a Hashtable.
+     * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as defined in the
+     * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> specification. Analogous, the
+     * 'xmlns' prefix is resolved to <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a>
+     *
+     * @see #getNamespaceCount
+     * @see #getNamespacePrefix
+     * @see #getNamespaceUri
+     */
+    String getNamespace( String prefix );
+
+    // --------------------------------------------------------------------------
+    // miscellaneous reporting methods
+
+    /**
+     * Returns the current depth of the element. Outside the root element, the depth is 0. The depth is incremented by 1
+     * when a start tag is reached. The depth is decremented AFTER the end tag event was observed.
+     *
+     * <pre>
+     * &lt;!-- outside --&gt;     0
+     * &lt;root&gt;                  1
+     *   sometext                 1
+     *     &lt;foobar&gt;         2
+     *     &lt;/foobar&gt;        2
+     * &lt;/root&gt;              1
+     * &lt;!-- outside --&gt;     0
+     * </pre>
+     */
+    int getDepth();
+
+    /**
+     * Returns a short text describing the current parser state, including the position, a description of the current
+     * event and the data source if known. This method is especially useful to provide meaningful error messages and for
+     * debugging purposes.
+     */
+    String getPositionDescription();
+
+    /**
+     * Returns the current line number, starting from 1. When the parser does not know the current line number or can
+     * not determine it, -1 is returned (e.g. for WBXML).
+     *
+     * @return current line number or -1 if unknown.
+     */
+    int getLineNumber();
+
+    /**
+     * Returns the current column number, starting from 0. When the parser does not know the current column number or
+     * can not determine it, -1 is returned (e.g. for WBXML).
+     *
+     * @return current column number or -1 if unknown.
+     */
+    int getColumnNumber();
+
+    // --------------------------------------------------------------------------
+    // TEXT related methods
+
+    /**
+     * Checks whether the current TEXT event contains only whitespace characters. For IGNORABLE_WHITESPACE, this is
+     * always true. For TEXT and CDSECT, false is returned when the current event text contains at least one non-white
+     * space character. For any other event type an exception is thrown.
+     * <p>
+     * <b>Please note:</b> non-validating parsers are not able to distinguish whitespace and ignorable whitespace,
+     * except from whitespace outside the root element. Ignorable whitespace is reported as separate event, which is
+     * exposed via nextToken only.
+     */
+    boolean isWhitespace()
+            throws XmlPullParserException;
+
+    /**
+     * Returns the text content of the current event as String. The value returned depends on current event type, for
+     * example for TEXT event it is element content (this is typical case when next() is used). See description of
+     * nextToken() for detailed description of possible returned values for different types of events.
+     * <p>
+     * <strong>NOTE:</strong> in case of ENTITY_REF, this method returns the entity replacement text (or null if not
+     * available). This is the only case where getText() and getTextCharacters() return different values.
+     *
+     * @see #getEventType
+     * @see #next
+     * @see #nextToken
+     */
+    String getText();
+
+    /**
+     * Returns the buffer that contains the text of the current event, as well as the start offset and length relevant
+     * for the current event. See getText(), next() and nextToken() for description of possible returned values.
+     * <p>
+     * <strong>Please note:</strong> this buffer must not be modified and its content MAY change after a call to next()
+     * or nextToken(). This method will always return the same value as getText(), except for ENTITY_REF. In the case of
+     * ENTITY ref, getText() returns the replacement text and this method returns the actual input buffer containing the
+     * entity name. If getText() returns null, this method returns null as well and the values returned in the holder
+     * array MUST be -1 (both start and length).
+     *
+     * @see #getText
+     * @see #next
+     * @see #nextToken
+     * @param holderForStartAndLength Must hold an 2-element int array into which the start offset and length values
+     *            will be written.
+     * @return char buffer that contains the text of the current event (null if the current event has no text
+     *         associated).
+     */
+    char[] getTextCharacters( int[] holderForStartAndLength );
+
+    // --------------------------------------------------------------------------
+    // START_TAG / END_TAG shared methods
+
+    /**
+     * Returns the namespace URI of the current element. The default namespace is represented as empty string. If
+     * namespaces are not enabled, an empty String ("") is always returned. The current event must be START_TAG or
+     * END_TAG; otherwise, null is returned.
+     */
+    String getNamespace();
+
+    /**
+     * For START_TAG or END_TAG events, the (local) name of the current element is returned when namespaces are enabled.
+     * When namespace processing is disabled, the raw name is returned. For ENTITY_REF events, the entity name is
+     * returned. If the current event is not START_TAG, END_TAG, or ENTITY_REF, null is returned.
+     * <p>
+     * <b>Please note:</b> To reconstruct the raw element name when namespaces are enabled and the prefix is not null,
+     * you will need to add the prefix and a colon to localName..
+     */
+    String getName();
+
+    /**
+     * Returns the prefix of the current element. If the element is in the default namespace (has no prefix), null is
+     * returned. If namespaces are not enabled, or the current event is not START_TAG or END_TAG, null is returned.
+     */
+    String getPrefix();
+
+    /**
+     * Returns true if the current event is START_TAG and the tag is degenerated (e.g. &lt;foobar/&gt;).
+     * <p>
+     * <b>NOTE:</b> if the parser is not on START_TAG, an exception will be thrown.
+     */
+    boolean isEmptyElementTag()
+            throws XmlPullParserException;
+
+    // --------------------------------------------------------------------------
+    // START_TAG Attributes retrieval methods
+
+    /**
+     * Returns the number of attributes of the current start tag, or -1 if the current event type is not START_TAG
+     *
+     * @see #getAttributeNamespace
+     * @see #getAttributeName
+     * @see #getAttributePrefix
+     * @see #getAttributeValue
+     */
+    int getAttributeCount();
+
+    /**
+     * Returns the namespace URI of the attribute with the given index (starts from 0). Returns an empty string ("") if
+     * namespaces are not enabled or the attribute has no namespace. Throws an IndexOutOfBoundsException if the index is
+     * out of range or the current event type is not START_TAG.
+     * <p>
+     * <strong>NOTE:</strong> if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set then namespace attributes (xmlns:ns='...')
+     * must be reported with namespace <a href="http://www.w3.org/2000/xmlns/">http://www.w3.org/2000/xmlns/</a> (visit
+     * this URL for description!). The default namespace attribute (xmlns="...") will be reported with empty namespace.
+     * <p>
+     * <strong>NOTE:</strong>The xml prefix is bound as defined in
+     * <a href="http://www.w3.org/TR/REC-xml-names/#ns-using">Namespaces in XML</a> specification to
+     * "http://www.w3.org/XML/1998/namespace".
+     *
+     * @param index zero based index of attribute
+     * @return attribute namespace, empty string ("") is returned if namespaces processing is not enabled or namespaces
+     *         processing is enabled but attribute has no namespace (it has no prefix).
+     */
+    String getAttributeNamespace( int index );
+
+    /**
+     * Returns the local name of the specified attribute if namespaces are enabled or just attribute name if namespaces
+     * are disabled. Throws an IndexOutOfBoundsException if the index is out of range or current event type is not
+     * START_TAG.
+     *
+     * @param index zero based index of attribute
+     * @return attribute name (null is never returned)
+     */
+    String getAttributeName( int index );
+
+    /**
+     * Returns the prefix of the specified attribute Returns null if the element has no prefix. If namespaces are
+     * disabled it will always return null. Throws an IndexOutOfBoundsException if the index is out of range or current
+     * event type is not START_TAG.
+     *
+     * @param index zero based index of attribute
+     * @return attribute prefix or null if namespaces processing is not enabled.
+     */
+    String getAttributePrefix( int index );
+
+    /**
+     * Returns the type of the specified attribute If parser is non-validating it MUST return CDATA.
+     *
+     * @param index zero based index of attribute
+     * @return attribute type (null is never returned)
+     */
+    String getAttributeType( int index );
+
+    /**
+     * Returns if the specified attribute was not in input was declared in XML. If parser is non-validating it MUST
+     * always return false. This information is part of XML infoset:
+     *
+     * @param index zero based index of attribute
+     * @return false if attribute was in input
+     */
+    boolean isAttributeDefault( int index );
+
+    /**
+     * Returns the given attributes value. Throws an IndexOutOfBoundsException if the index is out of range or current
+     * event type is not START_TAG.
+     * <p>
+     * <strong>NOTE:</strong> attribute value must be normalized (including entity replacement text if PROCESS_DOCDECL
+     * is false) as described in <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section 3.3.3
+     * Attribute-Value Normalization</a>
+     *
+     * @see #defineEntityReplacementText
+     * @param index zero based index of attribute
+     * @return value of attribute (null is never returned)
+     */
+    String getAttributeValue( int index );
+
+    /**
+     * Returns the attributes value identified by namespace URI and namespace localName. If namespaces are disabled
+     * namespace must be null. If current event type is not START_TAG then IndexOutOfBoundsException will be thrown.
+     * <p>
+     * <strong>NOTE:</strong> attribute value must be normalized (including entity replacement text if PROCESS_DOCDECL
+     * is false) as described in <a href="http://www.w3.org/TR/REC-xml#AVNormalize">XML 1.0 section 3.3.3
+     * Attribute-Value Normalization</a>
+     *
+     * @see #defineEntityReplacementText
+     * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null
+     * @param name If namespaces enabled local name of attribute otherwise just attribute name
+     * @return value of attribute or null if attribute with given name does not exist
+     */
+    String getAttributeValue( String namespace, String name );
+
+    // --------------------------------------------------------------------------
+    // actual parsing methods
+
+    /**
+     * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.)
+     *
+     * @see #next()
+     * @see #nextToken()
+     */
+    int getEventType()
+            throws XmlPullParserException;
+
+    /**
+     * Get next parsing event - element content wil be coalesced and only one TEXT event must be returned for whole
+     * element content (comments and processing instructions will be ignored and entity references must be expanded or
+     * exception mus be thrown if entity reference can not be expanded). If element content is empty (content is "")
+     * then no TEXT event will be reported.
+     * <p>
+     * <b>NOTE:</b> empty element (such as &lt;tag/&gt;) will be reported with two separate events: START_TAG, END_TAG - it
+     * must be so to preserve parsing equivalency of empty element to &lt;tag&gt;&lt;/tag&gt;. (see isEmptyElementTag ())
+     *
+     * @see #isEmptyElementTag
+     * @see #START_TAG
+     * @see #TEXT
+     * @see #END_TAG
+     * @see #END_DOCUMENT
+     */
+
+    int next()
+            throws XmlPullParserException, IOException;
+
+    /**
+     * This method works similarly to next() but will expose additional event types (COMMENT, CDSECT, DOCDECL,
+     * ENTITY_REF, PROCESSING_INSTRUCTION, or IGNORABLE_WHITESPACE) if they are available in input.
+     * <p>
+     * If special feature <a href="http://xmlpull.org/v1/doc/features.html#xml-roundtrip">FEATURE_XML_ROUNDTRIP</a>
+     * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip) is enabled it is possible to do XML
+     * document round trip ie. reproduce exactly on output the XML input using getText(): returned content is always
+     * unnormalized (exactly as in input). Otherwise returned content is end-of-line normalized as described
+     * <a href="http://www.w3.org/TR/REC-xml#sec-line-ends">XML 1.0 End-of-Line Handling</a> and. Also when this feature
+     * is enabled exact content of START_TAG, END_TAG, DOCDECL and PROCESSING_INSTRUCTION is available.
+     * <p>
+     * Here is the list of tokens that can be returned from nextToken() and what getText() and getTextCharacters()
+     * returns:
+     * <dl>
+     * <dt>START_DOCUMENT
+     * <dd>null
+     * <dt>END_DOCUMENT
+     * <dd>null
+     * <dt>START_TAG
+     * <dd>null unless FEATURE_XML_ROUNDTRIP enabled and then returns XML tag, ex: &lt;tag attr='val'&gt;
+     * <dt>END_TAG
+     * <dd>null unless FEATURE_XML_ROUNDTRIP id enabled and then returns XML tag, ex: &lt;/tag&gt;
+     * <dt>TEXT
+     * <dd>return element content. <br>
+     * Note: that element content may be delivered in multiple consecutive TEXT events.
+     * <dt>IGNORABLE_WHITESPACE
+     * <dd>return characters that are determined to be ignorable white space. If the FEATURE_XML_ROUNDTRIP is enabled
+     * all whitespace content outside root element will always reported as IGNORABLE_WHITESPACE otherwise reporting is
+     * optional. <br>
+     * Note: that element content may be delivered in multiple consecutive IGNORABLE_WHITESPACE events.
+     * <dt>CDSECT
+     * <dd>return text <em>inside</em> CDATA (ex. 'fo&lt;o' from &lt;!CDATA[fo&lt;o]]&gt;)
+     * <dt>PROCESSING_INSTRUCTION
+     * <dd>if FEATURE_XML_ROUNDTRIP is true return exact PI content ex: 'pi foo' from &lt;?pi foo?&gt; otherwise it may be
+     * exact PI content or concatenation of PI target, space and data so for example for &lt;?target data?&gt; string
+     * &quot;target data&quot; may be returned if FEATURE_XML_ROUNDTRIP is false.
+     * <dt>COMMENT
+     * <dd>return comment content ex. 'foo bar' from &lt;!--foo bar--&gt;
+     * <dt>ENTITY_REF
+     * <dd>getText() MUST return entity replacement text if PROCESS_DOCDECL is false otherwise getText() MAY return
+     * null, additionally getTextCharacters() MUST return entity name (for example 'entity_name' for &amp;entity_name;).
+     * <br>
+     * <b>NOTE:</b> this is the only place where value returned from getText() and getTextCharacters() <b>are
+     * different</b> <br>
+     * <b>NOTE:</b> it is user responsibility to resolve entity reference if PROCESS_DOCDECL is false and there is no
+     * entity replacement text set in defineEntityReplacementText() method (getText() will be null) <br>
+     * <b>NOTE:</b> character entities (ex. &amp;#32;) and standard entities such as &amp;amp; &amp;lt; &amp;gt;
+     * &amp;quot; &amp;apos; are reported as well and are <b>not</b> reported as TEXT tokens but as ENTITY_REF tokens!
+     * This requirement is added to allow to do roundtrip of XML documents!
+     * <dt>DOCDECL
+     * <dd>if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false then return what is inside of DOCDECL for
+     * example it returns:
+     *
+     * <pre>
+     * &quot; titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+     * [&lt;!ENTITY % active.links "INCLUDE"&gt;]&quot;
+     * </pre>
+     * <p>
+     * for input document that contained:
+     *
+     * <pre>
+     * &lt;!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
+     * [&lt;!ENTITY % active.links "INCLUDE"&gt;]&gt;
+     * </pre>
+     *
+     * otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true then what is returned is undefined (it
+     * may be even null)</dd>
+     * </dl>
+     * <p>
+     * <strong>NOTE:</strong> there is no guarantee that there will only one TEXT or IGNORABLE_WHITESPACE event from
+     * nextToken() as parser may chose to deliver element content in multiple tokens (dividing element content into
+     * chunks)
+     * <p>
+     * <strong>NOTE:</strong> whether returned text of token is end-of-line normalized is depending on
+     * FEATURE_XML_ROUNDTRIP.
+     * <p>
+     * <strong>NOTE:</strong> XMLDecl (&lt;?xml ...?&gt;) is not reported but its content is available through optional
+     * properties (see class description above).
+     *
+     * @see #next
+     * @see #START_TAG
+     * @see #TEXT
+     * @see #END_TAG
+     * @see #END_DOCUMENT
+     * @see #COMMENT
+     * @see #DOCDECL
+     * @see #PROCESSING_INSTRUCTION
+     * @see #ENTITY_REF
+     * @see #IGNORABLE_WHITESPACE
+     */
+    int nextToken()
+            throws XmlPullParserException, IOException;
+
+    // -----------------------------------------------------------------------------
+    // utility methods to mak XML parsing easier ...
+
+    /**
+     * Test if the current event is of the given type and if the namespace and name do match. null will match any
+     * namespace and any name. If the test is not passed, an exception is thrown. The exception text indicates the
+     * parser position, the expected event and the current event that is not meeting the requirement.
+     * <p>
+     * Essentially it does this
+     *
+     * <pre>
+     * if ( type != getEventType() || ( namespace != null &amp;&amp; !namespace.equals( getNamespace() ) )
+     *     || ( name != null &amp;&amp; !name.equals( getName() ) ) )
+     *     throw new XmlPullParserException( "expected " + TYPES[type] + getPositionDescription() );
+     * </pre>
+     */
+    void require( int type, String namespace, String name )
+            throws XmlPullParserException, IOException;
+
+    /**
+     * If current event is START_TAG then if next element is TEXT then element content is returned or if next event is
+     * END_TAG then empty string is returned, otherwise exception is thrown. After calling this function successfully
+     * parser will be positioned on END_TAG.
+     * <p>
+     * The motivation for this function is to allow to parse consistently both empty elements and elements that has non
+     * empty content, for example for input:
+     * <ol>
+     * <li>&lt;tag&gt;foo&lt;/tag&gt;
+     * <li>&lt;tag&gt;&lt;/tag&gt; (which is equivalent to &lt;tag/&gt; both input can be parsed with the same code:
+     *
+     * <pre>
+     *   p.nextTag()
+     *   p.requireEvent(p.START_TAG, "", "tag");
+     *   String content = p.nextText();
+     *   p.requireEvent(p.END_TAG, "", "tag");
+     * </pre></li></ol>
+     *
+     * This function together with nextTag make it very easy to parse XML that has no mixed content.
+     * <p>
+     * Essentially it does this
+     *
+     * <pre>
+     * if ( getEventType() != START_TAG )
+     * {
+     *     throw new XmlPullParserException( "parser must be on START_TAG to read next text", this, null );
+     * }
+     * int eventType = next();
+     * if ( eventType == TEXT )
+     * {
+     *     String result = getText();
+     *     eventType = next();
+     *     if ( eventType != END_TAG )
+     *     {
+     *         throw new XmlPullParserException( "event TEXT it must be immediately followed by END_TAG", this, null );
+     *     }
+     *     return result;
+     * }
+     * else if ( eventType == END_TAG )
+     * {
+     *     return "";
+     * }
+     * else
+     * {
+     *     throw new XmlPullParserException( "parser must be on START_TAG or TEXT to read text", this, null );
+     * }
+     * </pre>
+     */
+    String nextText()
+            throws XmlPullParserException, IOException;
+
+    /**
+     * Call next() and return event if it is START_TAG or END_TAG otherwise throw an exception. It will skip whitespace
+     * TEXT before actual tag if any.
+     * <p>
+     * essentially it does this
+     *
+     * <pre>
+     * int eventType = next();
+     * if ( eventType == TEXT &amp;&amp; isWhitespace() )
+     * { // skip whitespace
+     *     eventType = next();
+     * }
+     * if ( eventType != START_TAG &amp;&amp; eventType != END_TAG )
+     * {
+     *     throw new XmlPullParserException( "expected start or end tag", this, null );
+     * }
+     * return eventType;
+     * </pre>
+     */
+    int nextTag()
+            throws XmlPullParserException, IOException;
+
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java
new file mode 100644
index 0000000..2d9c9d1
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlPullParserException.java
@@ -0,0 +1,55 @@
+/* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.apache.camel.xml.io;
+
+/**
+ * This exception is thrown to signal XML Pull Parser related faults.
+ *
+ * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
+ */
+public class XmlPullParserException
+        extends Exception
+{
+    protected int row = -1;
+
+    protected int column = -1;
+
+    public XmlPullParserException( String s )
+    {
+        super( s );
+    }
+
+    /*
+     * public XmlPullParserException(String s, Throwable throwable) { super(s); this.detail = throwable; } public
+     * XmlPullParserException(String s, int row, int column) { super(s); this.row = row; this.column = column; }
+     */
+
+    public XmlPullParserException(String msg, XmlPullParser parser, Throwable cause )
+    {
+        super( ( msg == null ? "" : msg + " " )
+                + ( parser == null ? "" : "(position:" + parser.getPositionDescription() + ") " )
+                + ( cause == null ? "" : "caused by: " + cause ), cause );
+
+        if ( parser != null )
+        {
+            this.row = parser.getLineNumber();
+            this.column = parser.getColumnNumber();
+        }
+        if (cause != null)
+        {
+            initCause(cause);
+        }
+    }
+
+    public int getLineNumber()
+    {
+        return row;
+    }
+
+    public int getColumnNumber()
+    {
+        return column;
+    }
+
+}
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java
new file mode 100644
index 0000000..a3d52a7
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReader.java
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * 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.apache.camel.xml.io;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Character stream that handles (or at least attemtps to) all the necessary Voodo to figure out the
+ * charset encoding of the XML document within the stream.
+ * <p>
+ * IMPORTANT: This class is not related in any way to the org.xml.sax.XMLReader. This one IS a
+ * character stream.
+ * <p>
+ * All this has to be done without consuming characters from the stream, if not the XML parser will
+ * not recognized the document as a valid XML. This is not 100% true, but it's close enough (UTF-8
+ * BOM is not handled by all parsers right now, XmlReader handles it and things work in all
+ * parsers).
+ * <p>
+ * The XmlReader class handles the charset encoding of XML documents in Files, raw streams and HTTP
+ * streams by offering a wide set of constructors.
+ * <P>
+ * By default the charset encoding detection is lenient, the constructor with the lenient flag can
+ * be used for an script (following HTTP MIME and XML specifications). All this is nicely explained
+ * by Mark Pilgrim in his blog, <a
+ * href="https://web.archive.org/web/20060706153721/http://diveintomark.org/archives/2004/02/13/xml-media-types">
+ * Determining the character encoding of a feed</a>.
+ */
+public class XmlStreamReader extends Reader {
+
+    private static final int BUFFER_SIZE = 4096;
+    private static final String US_ASCII = "US-ASCII";
+    private static final String UTF_8 = "UTF-8";
+    private static final String UTF_16BE = "UTF-16BE";
+    private static final String UTF_16LE = "UTF-16LE";
+    private static final String UTF_16 = "UTF-16";
+    private static final String CP1047 = "CP1047";
+    private static final Pattern CHARSET_PATTERN = Pattern.compile("charset=([.[^; ]]*)");
+    private static final Pattern ENCODING_PATTERN = Pattern.compile("<\\?xml.*encoding[\\s]*=[\\s]*((?:\".[^\"]*\")|(?:'.[^']*'))", Pattern.MULTILINE);
+    private static final MessageFormat RAW_EX_1 = new MessageFormat("Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch");
+    private static final MessageFormat RAW_EX_2 = new MessageFormat("Invalid encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] unknown BOM");
+    private static final MessageFormat HTTP_EX_1 = new MessageFormat(
+            "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], BOM must be NULL");
+    private static final MessageFormat HTTP_EX_2 = new MessageFormat(
+            "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], encoding mismatch");
+    private static final MessageFormat HTTP_EX_3 = new MessageFormat(
+            "Invalid encoding, CT-MIME [{0}] CT-Enc [{1}] BOM [{2}] XML guess [{3}] XML prolog [{4}], Invalid MIME");
+
+    private static String staticDefaultEncoding = null;
+
+    private final String defaultEncoding;
+
+    private Reader reader;
+    private String encoding;
+
+    /**
+     * Creates a Reader for a File.
+     * <p>
+     * It looks for the UTF-8 BOM first, if none sniffs the XML prolog charset, if this is also
+     * missing defaults to UTF-8.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param file File to create a Reader from.
+     * @throws IOException thrown if there is a problem reading the file.
+     *
+     */
+    public XmlStreamReader(final File file) throws IOException {
+        this(new FileInputStream(file));
+    }
+
+    /**
+     * Creates a Reader for a raw InputStream.
+     * <p>
+     * It follows the same logic used for files.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param is InputStream to create a Reader from.
+     * @throws IOException thrown if there is a problem reading the stream.
+     *
+     */
+    public XmlStreamReader(final InputStream is) throws IOException {
+        this(is, true);
+    }
+
+    /**
+     * Creates a Reader for a raw InputStream and uses the provided default encoding if none is
+     * determined.
+     * <p>
+     * It follows the same logic used for files.
+     * <p>
+     * If lenient detection is indicated and the detection above fails as per specifications it then
+     * attempts the following:
+     * <p>
+     * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+     * again.
+     * <p>
+     * Else if the XML prolog had a charset encoding that encoding is used.
+     * <p>
+     * Else if the content type had a charset encoding that encoding is used.
+     * <p>
+     * Else 'UTF-8' is used.
+     * <p>
+     * If lenient detection is indicated an XmlStreamReaderException is never thrown.
+     * <p>
+     *
+     * @param is InputStream to create a Reader from.
+     * @param lenient indicates if the charset encoding detection should be relaxed.
+     * @param defaultEncoding default encoding to use if one cannot be detected.
+     * @throws IOException thrown if there is a problem reading the stream.
+     * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+     *             to the specs.
+     *
+     */
+    public XmlStreamReader(final InputStream is, final boolean lenient, final String defaultEncoding) throws IOException, XmlStreamReaderException {
+        if (defaultEncoding == null) {
+            this.defaultEncoding = staticDefaultEncoding;
+        } else {
+            this.defaultEncoding = defaultEncoding;
+        }
+        try {
+            doRawStream(is, lenient);
+        } catch (final XmlStreamReaderException ex) {
+            if (!lenient) {
+                throw ex;
+            } else {
+                doLenientDetection(null, ex);
+            }
+        }
+    }
+
+    /**
+     * Creates a Reader for a raw InputStream.
+     * <p>
+     * It follows the same logic used for files.
+     * <p>
+     * If lenient detection is indicated and the detection above fails as per specifications it then
+     * attempts the following:
+     * <p>
+     * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+     * again.
+     * <p>
+     * Else if the XML prolog had a charset encoding that encoding is used.
+     * <p>
+     * Else if the content type had a charset encoding that encoding is used.
+     * <p>
+     * Else 'UTF-8' is used.
+     * <p>
+     * If lenient detection is indicated an XmlStreamReaderException is never thrown.
+     * <p>
+     *
+     * @param is InputStream to create a Reader from.
+     * @param lenient indicates if the charset encoding detection should be relaxed.
+     * @throws IOException thrown if there is a problem reading the stream.
+     * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+     *             to the specs.
+     *
+     */
+    public XmlStreamReader(final InputStream is, final boolean lenient) throws IOException, XmlStreamReaderException {
+        this(is, lenient, null);
+    }
+
+    /**
+     * Creates a Reader using the InputStream of a URL.
+     * <p>
+     * If the URL is not of type HTTP and there is not 'content-type' header in the fetched data it
+     * uses the same logic used for Files.
+     * <p>
+     * If the URL is a HTTP Url or there is a 'content-type' header in the fetched data it uses the
+     * same logic used for an InputStream with content-type.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param url URL to create a Reader from.
+     * @throws IOException thrown if there is a problem reading the stream of the URL.
+     *
+     */
+    public XmlStreamReader(final URL url) throws IOException {
+        this(url, null);
+    }
+
+    /**
+     * Creates a Reader using the InputStream of a URL.
+     * <p>
+     * If the URL is not of type HTTP and there is not 'content-type' header in the fetched data it
+     * uses the same logic used for Files.
+     * <p>
+     * If the URL is a HTTP Url or there is a 'content-type' header in the fetched data it uses the
+     * same logic used for an InputStream with content-type.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param url URL to create a Reader from.
+     * @param requestHeaders optional Map of headers to set on http request.
+     * @throws IOException thrown if there is a problem reading the stream of the URL.
+     *
+     */
+    public XmlStreamReader(final URL url, final Map<String, String> requestHeaders) throws IOException {
+        this(url.openConnection(), requestHeaders);
+    }
+
+    /**
+     * Creates a Reader using the InputStream of a URLConnection.
+     * <p>
+     * If the URLConnection is not of type HttpURLConnection and there is not 'content-type' header
+     * in the fetched data it uses the same logic used for files.
+     * <p>
+     * If the URLConnection is a HTTP Url or there is a 'content-type' header in the fetched data it
+     * uses the same logic used for an InputStream with content-type.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param conn URLConnection to create a Reader from.
+     * @throws IOException thrown if there is a problem reading the stream of the URLConnection.
+     *
+     */
+    public XmlStreamReader(final URLConnection conn) throws IOException {
+        this(conn, null);
+    }
+
+    /**
+     * Creates a Reader using the InputStream of a URLConnection.
+     * <p>
+     * If the URLConnection is not of type HttpURLConnection and there is not 'content-type' header
+     * in the fetched data it uses the same logic used for files.
+     * <p>
+     * If the URLConnection is a HTTP Url or there is a 'content-type' header in the fetched data it
+     * uses the same logic used for an InputStream with content-type.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param conn URLConnection to create a Reader from.
+     * @param requestHeaders optional Map of headers to set on http request.
+     * @throws IOException thrown if there is a problem reading the stream of the URLConnection.
+     *
+     */
+    public XmlStreamReader(final URLConnection conn, final Map<String, String> requestHeaders) throws IOException {
+        defaultEncoding = staticDefaultEncoding;
+        final boolean lenient = true;
+        if (conn instanceof HttpURLConnection) {
+            final Package pckg = this.getClass().getPackage();
+            setRequestHeader(conn, requestHeaders);
+            try {
+                doHttpStream(conn.getInputStream(), conn.getContentType(), lenient);
+            } catch (final XmlStreamReaderException ex) {
+                doLenientDetection(conn.getContentType(), ex);
+            }
+        } else if (conn.getContentType() != null) {
+            try {
+                doHttpStream(conn.getInputStream(), conn.getContentType(), lenient);
+            } catch (final XmlStreamReaderException ex) {
+                doLenientDetection(conn.getContentType(), ex);
+            }
+        } else {
+            try {
+                doRawStream(conn.getInputStream(), lenient);
+            } catch (final XmlStreamReaderException ex) {
+                doLenientDetection(null, ex);
+            }
+        }
+    }
+
+    /**
+     * Creates a Reader using an InputStream and the associated content-type header.
+     * <p>
+     * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+     * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+     * prolog encoding uses the default encoding mandated by the content-type MIME type.
+     * <p>
+     * It does a lenient charset encoding detection, check the constructor with the lenient
+     * parameter for details.
+     * <p>
+     *
+     * @param is InputStream to create the reader from.
+     * @param httpContentType content-type header to use for the resolution of the charset encoding.
+     * @throws IOException thrown if there is a problem reading the file.
+     *
+     */
+    public XmlStreamReader(final InputStream is, final String httpContentType) throws IOException {
+        this(is, httpContentType, true);
+    }
+
+    /**
+     * Creates a Reader using an InputStream and the associated content-type header.
+     * <p>
+     * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+     * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+     * prolog encoding uses the default encoding mandated by the content-type MIME type.
+     * <p>
+     * If lenient detection is indicated and the detection above fails as per specifications it then
+     * attempts the following:
+     * <p>
+     * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+     * again.
+     * <p>
+     * Else if the XML prolog had a charset encoding that encoding is used.
+     * <p>
+     * Else if the content type had a charset encoding that encoding is used.
+     * <p>
+     * Else 'UTF-8' is used.
+     * <p>
+     * If lenient detection is indicated and XmlStreamReaderException is never thrown.
+     * <p>
+     *
+     * @param is InputStream to create the reader from.
+     * @param httpContentType content-type header to use for the resolution of the charset encoding.
+     * @param lenient indicates if the charset encoding detection should be relaxed.
+     * @param defaultEncoding default encoding to use if one cannot be detected.
+     * @throws IOException thrown if there is a problem reading the file.
+     * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+     *             to the specs.
+     *
+     */
+    public XmlStreamReader(final InputStream is, final String httpContentType, final boolean lenient, final String defaultEncoding) throws IOException,
+            XmlStreamReaderException {
+        if (defaultEncoding == null) {
+            this.defaultEncoding = staticDefaultEncoding;
+        } else {
+            this.defaultEncoding = defaultEncoding;
+        }
+        try {
+            doHttpStream(is, httpContentType, lenient);
+        } catch (final XmlStreamReaderException ex) {
+            if (!lenient) {
+                throw ex;
+            } else {
+                doLenientDetection(httpContentType, ex);
+            }
+        }
+    }
+
+    /**
+     * Creates a Reader using an InputStream and the associated content-type header.
+     * <p>
+     * First it checks if the stream has BOM. If there is not BOM checks the content-type encoding.
+     * If there is not content-type encoding checks the XML prolog encoding. If there is not XML
+     * prolog encoding uses the default encoding mandated by the content-type MIME type.
+     * <p>
+     * If lenient detection is indicated and the detection above fails as per specifications it then
+     * attempts the following:
+     * <p>
+     * If the content type was 'text/html' it replaces it with 'text/xml' and tries the detection
+     * again.
+     * <p>
+     * Else if the XML prolog had a charset encoding that encoding is used.
+     * <p>
+     * Else if the content type had a charset encoding that encoding is used.
+     * <p>
+     * Else 'UTF-8' is used.
+     * <p>
+     * If lenient detection is indicated and XmlStreamReaderException is never thrown.
+     * <p>
+     *
+     * @param is InputStream to create the reader from.
+     * @param httpContentType content-type header to use for the resolution of the charset encoding.
+     * @param lenient indicates if the charset encoding detection should be relaxed.
+     * @throws IOException thrown if there is a problem reading the file.
+     * @throws XmlStreamReaderException thrown if the charset encoding could not be determined according
+     *             to the specs.
+     *
+     */
+    public XmlStreamReader(final InputStream is, final String httpContentType, final boolean lenient) throws IOException, XmlStreamReaderException {
+        this(is, httpContentType, lenient, null);
+    }
+
+    /**
+     * Returns the default encoding to use if none is set in HTTP content-type, XML prolog and the
+     * rules based on content-type are not adequate.
+     * <p/>
+     * If it is NULL the content-type based rules are used.
+     * <p/>
+     *
+     * @return the default encoding to use.
+     */
+    public static String getDefaultEncoding() {
+        return staticDefaultEncoding;
+    }
+
+    /**
+     * Sets the default encoding to use if none is set in HTTP content-type, XML prolog and the
+     * rules based on content-type are not adequate.
+     * <p/>
+     * If it is set to NULL the content-type based rules are used.
+     * <p/>
+     * By default it is NULL.
+     * <p/>
+     *
+     * @param encoding charset encoding to default to.
+     */
+    public static void setDefaultEncoding(final String encoding) {
+        staticDefaultEncoding = encoding;
+    }
+
+    /**
+     * Returns the charset encoding of the XmlReader.
+     * <p>
+     *
+     * @return charset encoding.
+     *
+     */
+    public String getEncoding() {
+        return encoding;
+    }
+
+    private void doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException {
+        if (httpContentType != null) {
+            if (httpContentType.startsWith("text/html")) {
+                httpContentType = httpContentType.substring("text/html".length());
+                httpContentType = "text/xml" + httpContentType;
+                try {
+                    doHttpStream(ex.getInputStream(), httpContentType, true);
+                    ex = null;
+                } catch (final XmlStreamReaderException ex2) {
+                    ex = ex2;
+                }
+            }
+        }
+        if (ex != null) {
+            String encoding = ex.getXmlEncoding();
+            if (encoding == null) {
+                encoding = ex.getContentTypeEncoding();
+            }
+            if (encoding == null) {
+                if (defaultEncoding == null) {
+                    encoding = UTF_8;
+                } else {
+                    encoding = defaultEncoding;
+                }
+            }
+            prepareReader(ex.getInputStream(), encoding);
+        }
+    }
+
+    @Override
+    public int read(final char[] buf, final int offset, final int len) throws IOException {
+        return reader.read(buf, offset, len);
+    }
+
+    /**
+     * Closes the XmlReader stream.
+     * <p>
+     *
+     * @throws IOException thrown if there was a problem closing the stream.
+     *
+     */
+    @Override
+    public void close() throws IOException {
+        reader.close();
+    }
+
+    private void doRawStream(final InputStream is, final boolean lenient) throws IOException {
+        final BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
+        final String bomEnc = getBOMEncoding(pis);
+        final String xmlGuessEnc = getXMLGuessEncoding(pis);
+        final String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
+        final String encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, pis);
+        prepareReader(pis, encoding);
+    }
+
+    private void doHttpStream(final InputStream is, final String httpContentType, final boolean lenient) throws IOException {
+        final BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
+        final String cTMime = getContentTypeMime(httpContentType);
+        final String cTEnc = getContentTypeEncoding(httpContentType);
+        final String bomEnc = getBOMEncoding(pis);
+        final String xmlGuessEnc = getXMLGuessEncoding(pis);
+        final String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
+        final String encoding = calculateHttpEncoding(cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc, pis, lenient);
+        prepareReader(pis, encoding);
+    }
+
+    private void prepareReader(final InputStream is, final String encoding) throws IOException {
+        reader = new InputStreamReader(is, encoding);
+        this.encoding = encoding;
+    }
+
+    // InputStream is passed for XmlStreamReaderException creation only
+    private String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) throws IOException {
+        String encoding;
+        if (bomEnc == null) {
+            if (xmlGuessEnc == null || xmlEnc == null) {
+                if (defaultEncoding == null) {
+                    encoding = UTF_8;
+                } else {
+                    encoding = defaultEncoding;
+                }
+            } else if (xmlEnc.equals(UTF_16) && (xmlGuessEnc.equals(UTF_16BE) || xmlGuessEnc.equals(UTF_16LE))) {
+                encoding = xmlGuessEnc;
+            } else {
+                encoding = xmlEnc;
+            }
+        } else if (bomEnc.equals(UTF_8)) {
+            if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) {
+                throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+            }
+            if (xmlEnc != null && !xmlEnc.equals(UTF_8)) {
+                throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+            }
+            encoding = UTF_8;
+        } else if (bomEnc.equals(UTF_16BE) || bomEnc.equals(UTF_16LE)) {
+            if (xmlGuessEnc != null && !xmlGuessEnc.equals(bomEnc)) {
+                throw new IOException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }));
+            }
+            if (xmlEnc != null && !xmlEnc.equals(UTF_16) && !xmlEnc.equals(bomEnc)) {
+                throw new XmlStreamReaderException(RAW_EX_1.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+            }
+            encoding = bomEnc;
+        } else {
+            throw new XmlStreamReaderException(RAW_EX_2.format(new Object[] { bomEnc, xmlGuessEnc, xmlEnc }), bomEnc, xmlGuessEnc, xmlEnc, is);
+        }
+        return encoding;
+    }
+
+    private void setRequestHeader(final URLConnection conn, final Map<String, String> requestHeaders) {
+        final Package pckg = this.getClass().getPackage();
+        if (pckg.getImplementationTitle() != null && pckg.getImplementationVersion() != null) {
+            conn.setRequestProperty("User-Agent", pckg.getImplementationTitle() + "/" + pckg.getImplementationVersion());
+        } else {
+            conn.setRequestProperty("User-Agent", "ROME");
+        }
+        if (requestHeaders != null) {
+            for (final Entry<String, String> requestHeader : requestHeaders.entrySet()) {
+                conn.setRequestProperty(requestHeader.getKey(), requestHeader.getValue());
+            }
+        }
+    }
+
+    // InputStream is passed for XmlStreamReaderException creation only
+    private String calculateHttpEncoding(final String cTMime, final String cTEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc,
+                                         final InputStream is, final boolean lenient) throws IOException {
+        String encoding;
+        if (lenient && xmlEnc != null) {
+            encoding = xmlEnc;
+        } else {
+            final boolean appXml = isAppXml(cTMime);
+            final boolean textXml = isTextXml(cTMime);
+            if (appXml || textXml) {
+                if (cTEnc == null) {
+                    if (appXml) {
+                        encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, is);
+                    } else {
+                        if (defaultEncoding == null) {
+                            encoding = US_ASCII;
+                        } else {
+                            encoding = defaultEncoding;
+                        }
+                    }
+                } else if (bomEnc != null && (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE))) {
+                    throw new XmlStreamReaderException(HTTP_EX_1.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc,
+                            xmlGuessEnc, xmlEnc, is);
+                } else if (cTEnc.equals(UTF_16)) {
+                    if (bomEnc != null && bomEnc.startsWith(UTF_16)) {
+                        encoding = bomEnc;
+                    } else {
+                        throw new XmlStreamReaderException(HTTP_EX_2.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc,
+                                xmlGuessEnc, xmlEnc, is);
+                    }
+                } else {
+                    encoding = cTEnc;
+                }
+            } else {
+                throw new XmlStreamReaderException(HTTP_EX_3.format(new Object[] { cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc }), cTMime, cTEnc, bomEnc, xmlGuessEnc,
+                        xmlEnc, is);
+            }
+        }
+        return encoding;
+    }
+
+    // returns MIME type or NULL if httpContentType is NULL
+    private static String getContentTypeMime(final String httpContentType) {
+        String mime = null;
+        if (httpContentType != null) {
+            final int i = httpContentType.indexOf(";");
+            if (i == -1) {
+                mime = httpContentType.trim();
+            } else {
+                mime = httpContentType.substring(0, i).trim();
+            }
+        }
+        return mime;
+    }
+
+    // returns charset parameter value, NULL if not present, NULL if
+    // httpContentType is NULL
+    private static String getContentTypeEncoding(final String httpContentType) {
+        String encoding = null;
+        if (httpContentType != null) {
+            final int i = httpContentType.indexOf(";");
+            if (i > -1) {
+                final String postMime = httpContentType.substring(i + 1);
+                final Matcher m = CHARSET_PATTERN.matcher(postMime);
+                if (m.find()) {
+                    encoding = m.group(1);
+                }
+                if (encoding != null) {
+                    encoding = encoding.toUpperCase(Locale.ENGLISH);
+                }
+            }
+            if (encoding != null && (encoding.startsWith("\"") && encoding.endsWith("\"") || encoding.startsWith("'") && encoding.endsWith("'"))) {
+                encoding = encoding.substring(1, encoding.length() - 1);
+            }
+        }
+        return encoding;
+    }
+
+    // returns the BOM in the stream, NULL if not present,
+    // if there was BOM the in the stream it is consumed
+    private static String getBOMEncoding(final BufferedInputStream is) throws IOException {
+        String encoding = null;
+        final int[] bytes = new int[3];
+        is.mark(3);
+        bytes[0] = is.read();
+        bytes[1] = is.read();
+        bytes[2] = is.read();
+
+        if (bytes[0] == 0xFE && bytes[1] == 0xFF) {
+            encoding = UTF_16BE;
+            is.reset();
+            is.read();
+            is.read();
+        } else if (bytes[0] == 0xFF && bytes[1] == 0xFE) {
+            encoding = UTF_16LE;
+            is.reset();
+            is.read();
+            is.read();
+        } else if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
+            encoding = UTF_8;
+        } else {
+            is.reset();
+        }
+        return encoding;
+    }
+
+    // returns the best guess for the encoding by looking the first bytes of the
+    // stream, '<?xm'
+    private static String getXMLGuessEncoding(final BufferedInputStream is) throws IOException {
+        String encoding = null;
+        final int[] bytes = new int[4];
+        is.mark(4);
+        bytes[0] = is.read();
+        bytes[1] = is.read();
+        bytes[2] = is.read();
+        bytes[3] = is.read();
+        is.reset();
+
+        if (bytes[0] == 0x00 && bytes[1] == 0x3C && bytes[2] == 0x00 && bytes[3] == 0x3F) {
+            encoding = UTF_16BE;
+        } else if (bytes[0] == 0x3C && bytes[1] == 0x00 && bytes[2] == 0x3F && bytes[3] == 0x00) {
+            encoding = UTF_16LE;
+        } else if (bytes[0] == 0x3C && bytes[1] == 0x3F && bytes[2] == 0x78 && bytes[3] == 0x6D) {
+            encoding = UTF_8;
+        } else if (bytes[0] == 0x4C && bytes[1] == 0x6F && bytes[2] == 0xA7 && bytes[3] == 0x94) {
+            encoding = CP1047;
+        }
+        return encoding;
+    }
+
+    // returns the encoding declared in the <?xml encoding=...?>, NULL if none
+    static String getXmlProlog(final InputStream is, final String guessedEnc) throws IOException {
+        String encoding = null;
+        if (guessedEnc != null) {
+            final byte[] bytes = new byte[BUFFER_SIZE];
+            is.mark(BUFFER_SIZE);
+            int offset = 0;
+            int max = BUFFER_SIZE;
+            int c = is.read(bytes, offset, max);
+            int firstGT = -1;
+            while (c != -1 && firstGT == -1 && offset < BUFFER_SIZE) {
+                offset += c;
+                max -= c;
+                c = is.read(bytes, offset, max);
+                firstGT = new String(bytes, 0, offset, guessedEnc).indexOf(">");
+            }
+            if (firstGT == -1) {
+                if (c == -1) {
+                    throw new IOException("Unexpected end of XML stream");
+                } else {
+                    throw new IOException("XML prolog or ROOT element not found on first " + offset + " bytes");
+                }
+            }
+            final int bytesRead = offset;
+            if (bytesRead > 0) {
+                is.reset();
+                String prolog = new String(bytes, guessedEnc).substring(0, firstGT);
+                final Matcher m = ENCODING_PATTERN.matcher(prolog);
+                if (m.find()) {
+                    encoding = m.group(1).toUpperCase(Locale.ENGLISH);
+                    encoding = encoding.substring(1, encoding.length() - 1);
+                }
+            }
+        }
+        return encoding;
+    }
+
+    // indicates if the MIME type belongs to the APPLICATION XML family
+    private static boolean isAppXml(final String mime) {
+        return mime != null
+                && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime.equals("application/xml-external-parsed-entity") || mime
+                .startsWith("application/") && mime.endsWith("+xml"));
+    }
+
+    // indicates if the MIME type belongs to the TEXT XML family
+    private static boolean isTextXml(final String mime) {
+        return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime.startsWith("text/") && mime.endsWith("+xml"));
+    }
+
+}
\ No newline at end of file
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java
new file mode 100644
index 0000000..97d798c
--- /dev/null
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/io/XmlStreamReaderException.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc.
+ *
+ * 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.apache.camel.xml.io;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * The XmlReaderException is thrown by the XmlReader constructors if the charset encoding can not be
+ * determined according to the XML 1.0 specification and RFC 3023.
+ * <p>
+ * The exception returns the unconsumed InputStream to allow the application to do an alternate
+ * processing with the stream. Note that the original InputStream given to the XmlReader cannot be
+ * used as that one has been already read.
+ */
+public class XmlStreamReaderException extends IOException {
+    private static final long serialVersionUID = 1L;
+    private final String bomEncoding;
+    private final String xmlGuessEncoding;
+    private final String xmlEncoding;
+    private final String contentTypeMime;
+    private final String contentTypeEncoding;
+    private final InputStream is;
+
+    /**
+     * Creates an exception instance if the charset encoding could not be determined.
+     * <p>
+     * Instances of this exception are thrown by the XmlReader.
+     * <p>
+     *
+     * @param msg message describing the reason for the exception.
+     * @param bomEnc BOM encoding.
+     * @param xmlGuessEnc XML guess encoding.
+     * @param xmlEnc XML prolog encoding.
+     * @param is the unconsumed InputStream.
+     *
+     */
+    public XmlStreamReaderException(final String msg, final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final InputStream is) {
+        this(msg, null, null, bomEnc, xmlGuessEnc, xmlEnc, is);
+    }
+
+    /**
+     * Creates an exception instance if the charset encoding could not be determined.
+     * <p>
+     * Instances of this exception are thrown by the XmlReader.
+     * <p>
+     *
+     * @param msg message describing the reason for the exception.
+     * @param ctMime MIME type in the content-type.
+     * @param ctEnc encoding in the content-type.
+     * @param bomEnc BOM encoding.
+     * @param xmlGuessEnc XML guess encoding.
+     * @param xmlEnc XML prolog encoding.
+     * @param is the unconsumed InputStream.
+     *
+     */
+    public XmlStreamReaderException(final String msg, final String ctMime, final String ctEnc, final String bomEnc, final String xmlGuessEnc, final String xmlEnc,
+                                    final InputStream is) {
+        super(msg);
+        contentTypeMime = ctMime;
+        contentTypeEncoding = ctEnc;
+        bomEncoding = bomEnc;
+        xmlGuessEncoding = xmlGuessEnc;
+        xmlEncoding = xmlEnc;
+        this.is = is;
+    }
+
+    /**
+     * Returns the BOM encoding found in the InputStream.
+     * <p>
+     *
+     * @return the BOM encoding, null if none.
+     *
+     */
+    public String getBomEncoding() {
+        return bomEncoding;
+    }
+
+    /**
+     * Returns the encoding guess based on the first bytes of the InputStream.
+     * <p>
+     *
+     * @return the encoding guess, null if it couldn't be guessed.
+     *
+     */
+    public String getXmlGuessEncoding() {
+        return xmlGuessEncoding;
+    }
+
+    /**
+     * Returns the encoding found in the XML prolog of the InputStream.
+     * <p>
+     *
+     * @return the encoding of the XML prolog, null if none.
+     *
+     */
+    public String getXmlEncoding() {
+        return xmlEncoding;
+    }
+
+    /**
+     * Returns the MIME type in the content-type used to attempt determining the encoding.
+     * <p>
+     *
+     * @return the MIME type in the content-type, null if there was not content-type or the encoding
+     *         detection did not involve HTTP.
+     *
+     */
+    public String getContentTypeMime() {
+        return contentTypeMime;
+    }
+
+    /**
+     * Returns the encoding in the content-type used to attempt determining the encoding.
+     * <p>
+     *
+     * @return the encoding in the content-type, null if there was not content-type, no encoding in
+     *         it or the encoding detection did not involve HTTP.
+     *
+     */
+    public String getContentTypeEncoding() {
+        return contentTypeEncoding;
+    }
+
+    /**
+     * Returns the unconsumed InputStream to allow the application to do an alternate encoding
+     * detection on the InputStream.
+     * <p>
+     *
+     * @return the unconsumed InputStream.
+     *
+     */
+    public InputStream getInputStream() {
+        return is;
+    }
+}
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
new file mode 100644
index 0000000..c90a932
--- /dev/null
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.xml.in;
+
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestsDefinition;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+
+public class ModelParserTest {
+
+    public static final String NAMESPACE = "http://camel.apache.org/schema/spring";
+    private static List<String> REST_XMLS = Arrays.asList("barRest.xml", "simpleRest.xml", "simpleRestToD.xml");
+
+    @Test
+    public void testFiles() throws Exception {
+        Path dir = getResourceFolder();
+        List<Path> files = Files.list(dir).sorted().filter(Files::isRegularFile).collect(Collectors.toList());
+        for (Path path : files) {
+            ModelParser parser = new ModelParser(Files.newInputStream(path), NAMESPACE);
+            boolean isRest = REST_XMLS.contains(path.getFileName().toString());
+            if (isRest) {
+                RestsDefinition rests = parser.parseRestsDefinition();
+                assertNotNull(rests);
+            } else {
+                RoutesDefinition routes = parser.parseRoutesDefinition();
+                assertNotNull(routes);
+            }
+        }
+    }
+
+    @Test
+    public void testSimpleString() throws Exception {
+        RoutesDefinition routes = new ModelParser(new StringReader(
+                "<routes>" +
+                        "<route id='foo'>" +
+                            "<from uri='my:bar'/>" +
+                            "<to uri='mock:res'/>" +
+                        "</route>" +
+                "</routes>"
+        )).parseRoutesDefinition();
+        assertNotNull(routes);
+    }
+
+    private Path getResourceFolder() {
+        String url = getClass().getClassLoader().getResource("barInterceptorRoute.xml").toString();
+        if (url.startsWith("file:")) {
+            url = url.substring("file:".length(), url.indexOf("barInterceptorRoute.xml"));
+        } else if (url.startsWith("jar:file:")) {
+            url = url.substring("jar:file:".length(), url.indexOf("!"));
+        }
+        return Paths.get(url);
+    }
+}
diff --git a/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml b/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml
new file mode 100644
index 0000000..c7dbf76
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barInterceptorRoute.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+    <route id="bar">
+        <from uri="direct:bar"/>
+        <intercept>
+            <to uri="log:intercept"/>
+            <to uri="mock:intercept"/>
+        </intercept>
+        <to uri="mock:bar"/>
+    </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml b/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml
new file mode 100644
index 0000000..7eda513
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barOnExceptionRoute.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+    <route id="bar">
+        <from uri="direct:bar"/>
+        <onException>
+            <exception>java.lang.Exception</exception>
+            <handled>
+                <constant>true</constant>
+            </handled>
+            <to uri="log:error"/>
+            <to uri="mock:error"/>
+        </onException>
+        <process ref="myProcessor"/>
+        <to uri="log:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barPolicyRoute.xml b/core/camel-xml-io/src/test/resources/barPolicyRoute.xml
new file mode 100644
index 0000000..f7ce1ad
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barPolicyRoute.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring">
+
+    <route id="foo">
+        <from uri="direct:start"/>
+        <policy ref="foo">
+            <to uri="mock:foo"/>
+            <to uri="mock:bar"/>
+            <to uri="mock:result"/>
+        </policy>
+    </route>
+
+    <route id="bar">
+        <from uri="direct:send"/>
+        <to uri="direct:start"/>
+        <to uri="mock:response"/>
+    </route>
+
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/barRest.xml b/core/camel-xml-io/src/test/resources/barRest.xml
new file mode 100644
index 0000000..dc50305
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barRest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<rests xmlns="http://camel.apache.org/schema/spring">
+	<rest id="bar" path="/say/hello">
+	    <get uri="/bar">
+	      <to uri="mock:bar"/>
+	    </get>
+    </rest>
+</rests>
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/barRoute.xml b/core/camel-xml-io/src/test/resources/barRoute.xml
new file mode 100644
index 0000000..e96c1f2
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barRoute.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<!-- START SNIPPET: e1 -->
+<routes xmlns="http://camel.apache.org/schema/spring">
+    <!-- here we define the bar route -->
+    <route id="bar">
+        <from uri="direct:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+
+    <!-- we could add more routes if we like,
+         but in this example we stick to one route only -->
+</routes>
+<!-- END SNIPPET: e1 -->
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml b/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml
new file mode 100644
index 0000000..e7ce805
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/barUpdatedRoute.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<!-- START SNIPPET: e1 -->
+<routes xmlns="http://camel.apache.org/schema/spring">
+    <!-- here we define the bar route -->
+    <route id="bar">
+        <from uri="direct:bar"/>
+        <transform>
+          <simple>Bye ${body}</simple>
+        </transform>
+        <to uri="mock:bar"/>
+    </route>
+
+    <!-- we could add more routes if we like,
+         but in this example we stick to one route only -->
+</routes>
+<!-- END SNIPPET: e1 -->
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/convertBody.xml b/core/camel-xml-io/src/test/resources/convertBody.xml
new file mode 100644
index 0000000..7b66154
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/convertBody.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <convertBodyTo type="java.lang.Integer"/>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml b/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml
new file mode 100644
index 0000000..d924ded
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/dynamicRecipientList.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <recipientList>
+      <header>foo</header>
+    </recipientList>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/loop.xml b/core/camel-xml-io/src/test/resources/loop.xml
new file mode 100644
index 0000000..9aa9214
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/loop.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="direct:a"/>
+    <loop>
+      <constant>8</constant>
+    </loop>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processor.xml b/core/camel-xml-io/src/test/resources/processor.xml
new file mode 100644
index 0000000..07b319a
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processor.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <process ref="myProcessor"/>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithFilter.xml b/core/camel-xml-io/src/test/resources/processorWithFilter.xml
new file mode 100644
index 0000000..975a53d
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithFilter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <filter>
+      <language language="juel">in.header.foo == 'bar'</language>
+      <process ref="myProcessor"/>
+    </filter>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml b/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml
new file mode 100644
index 0000000..7edf514
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithGroovyFilter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <filter>
+      <groovy>in.headers.any { h -> h.startsWith('foo')}</groovy>
+      <process ref="myProcessor"/>
+    </filter>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml b/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml
new file mode 100644
index 0000000..89d6540
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithHeaderFilter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <filter>
+      <header>foo</header>
+      <process ref="myProcessor"/>
+    </filter>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml b/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml
new file mode 100644
index 0000000..e5d5884
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/processorWithSimpleFilter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <filter>
+      <simple>${in.header.foo} == 'bar'</simple>
+      <process ref="myProcessor"/>
+    </filter>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/resequencerBatch.xml b/core/camel-xml-io/src/test/resources/resequencerBatch.xml
new file mode 100644
index 0000000..69e42fe
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/resequencerBatch.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+    	<from uri="direct:start" />
+    	<resequence>
+            <!--
+                batch-config can be ommitted for default resequence settings
+            -->
+            <batch-config batchTimeout="2000" batchSize="500"/>
+    		<simple>body</simple>
+    		<to uri="mock:result" />
+    	</resequence>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/resequencerStream.xml b/core/camel-xml-io/src/test/resources/resequencerStream.xml
new file mode 100644
index 0000000..b9b4594
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/resequencerStream.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+    	<from uri="direct:start" />
+    	<resequence>
+            <stream-config timeout="2000"/> <!-- Use default capacity -->
+    		<simple>in.header.seqnum</simple>
+    		<to uri="mock:result" />
+    	</resequence>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeGroup.xml b/core/camel-xml-io/src/test/resources/routeGroup.xml
new file mode 100644
index 0000000..7548f8c
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeGroup.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <!--
+       xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"
+  -->
+
+  <route id="route-id" group="route-group">
+    <from uri="seda:a"/>
+    <to uri="seda:b"/>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeProperties.xml b/core/camel-xml-io/src/test/resources/routeProperties.xml
new file mode 100644
index 0000000..b425f6c
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeProperties.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <!--
+       xsi:schemaLocation="http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"
+  -->
+
+  <route id="route-id">
+    <routeProperty key="key1" value="val1"/>
+    <routeProperty key="key2" value="val2"/>
+
+    <from uri="seda:a"/>
+    <to uri="seda:b"/>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml
new file mode 100644
index 0000000..6aea276
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithBindyDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <bindy type="Csv" classType="org.apache.camel.MyFoo"/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithChoice.xml b/core/camel-xml-io/src/test/resources/routeWithChoice.xml
new file mode 100644
index 0000000..c74bcc7
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithChoice.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <choice>
+      <when>
+        <simple>${header.foo} == 'bar'</simple>
+        <to uri="seda:b"/>
+      </when>
+      <when>
+        <ognl>header[foo] == 'cheese'</ognl>
+        <to uri="seda:c"/>
+      </when>
+      <otherwise>
+        <to uri="seda:d"/>
+      </otherwise>
+    </choice>
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml
new file mode 100644
index 0000000..3c75b19
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithCircuitBreakerLoadBalance.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="direct:start"/>
+        <loadBalance>
+            <throwException exceptionType="java.lang.IllegalArgumentException" message="Forced"/>
+            <onFallback>
+                <transform>
+                    <constant>Fallback message</constant>
+                </transform>
+            </onFallback>
+            <to uri="mock:result"/>
+        </loadBalance>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml
new file mode 100644
index 0000000..3e94bc1
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithCvsDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <csv/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml
new file mode 100644
index 0000000..0df7b27
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithFailoverLoadBalance.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <loadBalance>
+            <failover>
+                <exception>java.io.IOException</exception>
+                <exception>java.text.ParseException</exception>
+            </failover>
+            <to uri="seda:b"/>
+            <to uri="seda:c"/>
+            <to uri="seda:d"/>
+        </loadBalance>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml
new file mode 100644
index 0000000..db33188
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithFlatpackDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <flatpack/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml
new file mode 100644
index 0000000..1ee6503
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithHL7DataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <hl7/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml
new file mode 100644
index 0000000..c8db92d
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithJSonDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <json library="Jackson"/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml
new file mode 100644
index 0000000..4bc91e9
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithJaxbDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <jaxb contextPath="org.apache.camel.model"/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml
new file mode 100644
index 0000000..5eab226
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithLoadBalance.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <loadBalance>
+       <roundRobin/>
+       <to uri="seda:b"/>      
+       <to uri="seda:c"/>      
+       <to uri="seda:d"/>       
+    </loadBalance>    
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithNamespace.xml b/core/camel-xml-io/src/test/resources/routeWithNamespace.xml
new file mode 100644
index 0000000..664e326
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithNamespace.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring" xmlns:foo="http://foo">
+    <route id="routeWithNamespace">
+        <from uri="direct:foo" />
+        <choice>
+            <when>
+                <xpath>/foo:foo/foo:bar = 'cheese'</xpath>
+                <setBody>
+                    <constant>Hello from foo</constant>
+                </setBody>
+                <to uri="mock:bar"/>
+            </when>
+        </choice>
+        <to uri="log:end"/>
+    </route>
+</routes>
\ No newline at end of file
diff --git a/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml
new file mode 100644
index 0000000..bbb79c0
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithRSSDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <rss/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml
new file mode 100644
index 0000000..de26430
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithRandomLoadBalance.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <loadBalance>
+            <random/>
+            <to uri="seda:b"/>
+            <to uri="seda:c"/>
+            <to uri="seda:d"/>
+        </loadBalance>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml
new file mode 100644
index 0000000..f8b0e79
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithStickyLoadBalance.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+  <route>
+    <from uri="seda:a"/>
+    <loadBalance>
+       <sticky>
+           <correlationExpression>
+               <language language="juel">in.header.foo == 'bar'</language>
+           </correlationExpression>
+       </sticky>
+       <to uri="seda:b"/>      
+       <to uri="seda:c"/>      
+       <to uri="seda:d"/>       
+    </loadBalance>    
+  </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml
new file mode 100644
index 0000000..f3939e5
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithTidyMarkupDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <unmarshal>
+                <tidyMarkup/>
+            </unmarshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml b/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml
new file mode 100644
index 0000000..5ade532
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithTopicLoadBalance.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <loadBalance>
+            <topic/>
+            <to uri="seda:b"/>
+            <to uri="seda:c"/>
+            <to uri="seda:d"/>
+        </loadBalance>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml
new file mode 100644
index 0000000..7ee7d50
--- /dev/null
+++ b/core/camel-xml-io/src/test/resources/routeWithXMLSecurityDataFormat.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<routes id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+        <from uri="seda:a"/>
+        <pipeline>
+            <marshal>
+                <secureXML/>
+            </marshal>
+            <to uri="seda:b"/>
+        </pipeline>
+    </route>
+</routes>
diff --git a/core/camel-xml-io/src/test/resources/routeWithXStreamDataFormat.xml b/core/camel-xml-io/src/test/resources/routeWithXStreamDataFormat.xml
... 1358 lines suppressed ...