This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 8b64682 SLING-8570 - Extract a generic Content Parser API from
org.apache.sling.jcr.contentparser with pluggable implementations
8b64682 is described below
commit 8b646824a0369b68662689cf03c6536db0309a60
Author: Radu Cotescu <[email protected]>
AuthorDate: Fri Jul 12 16:33:23 2019 +0200
SLING-8570 - Extract a generic Content Parser API from
org.apache.sling.jcr.contentparser with pluggable implementations
* extracted a test utils module, which can be used by all contentparser
implementations
* added a XML Content Parser implementation
---
.../org-apache-sling-contentparser-json/pom.xml | 6 +
.../json/internal/JsonContentParserTest.java | 3 +-
.../pom.xml | 59 ++++
.../sling/contentparser/testutils}/TestUtils.java | 12 +-
.../testutils}/mapsupport/ContentElement.java | 2 +-
.../mapsupport/ContentElementHandler.java | 2 +-
.../testutils}/mapsupport/ContentElementImpl.java | 2 +-
.../pom.xml | 30 +-
.../xml/internal/XmlContentParser.java | 224 ++++++++++++++
.../xml/internal/XmlContentParserTest.java} | 66 ++--
.../src/test/resources/content-test/content.xml | 334 +++++++++++++++++++++
.../invalid-test/contentWithObjectList.json | 14 +
.../src/test/resources/invalid-test/invalid.json | 1 +
contentparser/pom.xml | 42 +++
14 files changed, 725 insertions(+), 72 deletions(-)
diff --git a/contentparser/org-apache-sling-contentparser-json/pom.xml
b/contentparser/org-apache-sling-contentparser-json/pom.xml
index 3fc188b..7e6dbd9 100644
--- a/contentparser/org-apache-sling-contentparser-json/pom.xml
+++ b/contentparser/org-apache-sling-contentparser-json/pom.xml
@@ -88,6 +88,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.contentparser.testutils</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
b/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
index 3099ae8..b52e934 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
+++
b/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
@@ -29,7 +29,8 @@ import org.apache.sling.contentparser.api.ContentParser;
import org.apache.sling.contentparser.api.JsonParserFeature;
import org.apache.sling.contentparser.api.ParseException;
import org.apache.sling.contentparser.api.ParserOptions;
-import org.apache.sling.contentparser.json.internal.mapsupport.ContentElement;
+import org.apache.sling.contentparser.testutils.TestUtils;
+import org.apache.sling.contentparser.testutils.mapsupport.ContentElement;
import org.junit.Before;
import org.junit.Test;
diff --git a/contentparser/org-apache-sling-contentparser-testutils/pom.xml
b/contentparser/org-apache-sling-contentparser-testutils/pom.xml
new file mode 100644
index 0000000..2424af1
--- /dev/null
+++ b/contentparser/org-apache-sling-contentparser-testutils/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>35</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.contentparser.testutils</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+
+ <name>Apache Sling Content Parser Test Utilities</name>
+ <description>
+ Apache Sling Content Parser Test Utilities for the Content Parser API
implementations
+ </description>
+
+ <scm>
+
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-testutils.git</connection>
+
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-testutils.git</developerConnection>
+
<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-contentparser-testutils.git</url>
+ <tag>HEAD</tag>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.contentparser.api</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.8</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/TestUtils.java
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/TestUtils.java
similarity index 79%
rename from
contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/TestUtils.java
rename to
contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/TestUtils.java
index 0d81e36..339f8c5 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/TestUtils.java
+++
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/TestUtils.java
@@ -16,7 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.json.internal;
+package org.apache.sling.contentparser.testutils;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -27,8 +27,8 @@ import java.nio.charset.StandardCharsets;
import org.apache.sling.contentparser.api.ContentParser;
import org.apache.sling.contentparser.api.ParserOptions;
-import org.apache.sling.contentparser.json.internal.mapsupport.ContentElement;
-import
org.apache.sling.contentparser.json.internal.mapsupport.ContentElementHandler;
+import org.apache.sling.contentparser.testutils.mapsupport.ContentElement;
+import
org.apache.sling.contentparser.testutils.mapsupport.ContentElementHandler;
public final class TestUtils {
@@ -36,11 +36,11 @@ public final class TestUtils {
// static methods only
}
- static ContentElement parse(ContentParser contentParser, File file) throws
IOException {
+ public static ContentElement parse(ContentParser contentParser, File file)
throws IOException {
return parse(contentParser, new ParserOptions(), file);
}
- static ContentElement parse(ContentParser contentParser, ParserOptions
parserOptions, File file) throws IOException {
+ public static ContentElement parse(ContentParser contentParser,
ParserOptions parserOptions, File file) throws IOException {
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis)) {
ContentElementHandler handler = new ContentElementHandler();
@@ -49,7 +49,7 @@ public final class TestUtils {
}
}
- static ContentElement parse(ContentParser contentParser, String
jsonContent) throws IOException {
+ public static ContentElement parse(ContentParser contentParser, String
jsonContent) throws IOException {
try (ByteArrayInputStream is = new
ByteArrayInputStream(jsonContent.getBytes(StandardCharsets.UTF_8))) {
ContentElementHandler handler = new ContentElementHandler();
contentParser.parse(handler, is, new ParserOptions());
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElement.java
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElement.java
similarity index 96%
rename from
contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElement.java
rename to
contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElement.java
index 0a4457e..37bb5ad 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElement.java
+++
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElement.java
@@ -16,7 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.json.internal.mapsupport;
+package org.apache.sling.contentparser.testutils.mapsupport;
import java.util.Map;
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementHandler.java
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementHandler.java
similarity index 97%
rename from
contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementHandler.java
rename to
contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementHandler.java
index bc21ec0..c6e3f54 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementHandler.java
+++
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementHandler.java
@@ -16,7 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.json.internal.mapsupport;
+package org.apache.sling.contentparser.testutils.mapsupport;
import java.util.Map;
import java.util.regex.Matcher;
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementImpl.java
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementImpl.java
similarity index 97%
rename from
contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementImpl.java
rename to
contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementImpl.java
index ddbf9bd..93ec66e 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/mapsupport/ContentElementImpl.java
+++
b/contentparser/org-apache-sling-contentparser-testutils/src/main/java/org/apache/sling/contentparser/testutils/mapsupport/ContentElementImpl.java
@@ -16,7 +16,7 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.json.internal.mapsupport;
+package org.apache.sling.contentparser.testutils.mapsupport;
import java.util.LinkedHashMap;
import java.util.Map;
diff --git a/contentparser/org-apache-sling-contentparser-json/pom.xml
b/contentparser/org-apache-sling-contentparser-xml/pom.xml
similarity index 83%
copy from contentparser/org-apache-sling-contentparser-json/pom.xml
copy to contentparser/org-apache-sling-contentparser-xml/pom.xml
index 3fc188b..d2063ac 100644
--- a/contentparser/org-apache-sling-contentparser-json/pom.xml
+++ b/contentparser/org-apache-sling-contentparser-xml/pom.xml
@@ -27,18 +27,18 @@
<relativePath/>
</parent>
- <artifactId>org.apache.sling.contentparser.json</artifactId>
+ <artifactId>org.apache.sling.contentparser.xml</artifactId>
<version>0.9.0-SNAPSHOT</version>
- <name>Apache Sling Content Parser for JSON</name>
+ <name>Apache Sling Content Parser for XML</name>
<description>
- Apache Sling Content Parser for resource trees stored in JSON files
+ Apache Sling Content Parser for resource trees stored in XML files
</description>
<scm>
-
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-json.git</connection>
-
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-json.git</developerConnection>
-
<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-contentparser-json.git</url>
+
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-xml.git</connection>
+
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-contentparser-xml.git</developerConnection>
+
<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-contentparser-xml.git</url>
<tag>HEAD</tag>
</scm>
@@ -50,12 +50,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-json_1.0_spec</artifactId>
- <version>1.0-alpha-1</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
@@ -88,6 +82,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.contentparser.testutils</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
@@ -98,11 +98,5 @@
<version>15.0</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.apache.johnzon</groupId>
- <artifactId>johnzon-core</artifactId>
- <version>1.0.0</version>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
diff --git
a/contentparser/org-apache-sling-contentparser-xml/src/main/java/org/apache/sling/contentparser/xml/internal/XmlContentParser.java
b/contentparser/org-apache-sling-contentparser-xml/src/main/java/org/apache/sling/contentparser/xml/internal/XmlContentParser.java
new file mode 100644
index 0000000..5c18539
--- /dev/null
+++
b/contentparser/org-apache-sling-contentparser-xml/src/main/java/org/apache/sling/contentparser/xml/internal/XmlContentParser.java
@@ -0,0 +1,224 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.sling.contentparser.xml.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.contentparser.api.ContentHandler;
+import org.apache.sling.contentparser.api.ContentParser;
+import org.apache.sling.contentparser.api.ParseException;
+import org.apache.sling.contentparser.api.ParserHelper;
+import org.apache.sling.contentparser.api.ParserOptions;
+import org.osgi.service.component.annotations.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * Parses XML files that contains content fragments.
+ * Instance of this class is thread-safe.
+ */
+@Component(
+ property = {
+ ContentParser.SERVICE_PROPERTY_CONTENT_TYPE + "=" +
ContentParser.XML_CONTENT_TYPE
+ }
+)
+public final class XmlContentParser implements ContentParser {
+
+ private static final String JCR_PRIMARY_TYPE = "jcr:primaryType";
+ private final DocumentBuilderFactory documentBuilderFactory;
+
+ public XmlContentParser() {
+ documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ }
+
+ @Override
+ public void parse(ContentHandler handler, InputStream is, ParserOptions
parserOptions) throws IOException, ParseException {
+ try {
+ DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
+ Document doc = documentBuilder.parse(is);
+ parse(handler, doc.getDocumentElement(), parserOptions, null);
+ } catch (ParserConfigurationException | SAXException ex) {
+ throw new ParseException("Error parsing JCR XML content.", ex);
+ }
+ }
+
+ private void parse(ContentHandler handler, Element element, ParserOptions
parserOptions, String parentPath) {
+ // build node path
+ String path;
+ if (parentPath == null) {
+ path = "/";
+ } else {
+ String name = getChildText(element, "name");
+ if (StringUtils.isEmpty(name)) {
+ throw new ParseException("Child node without name detected
below path " + parentPath);
+ }
+ if (parserOptions.getIgnoreResourceNames().contains(name)) {
+ return;
+ }
+ path = parentPath.endsWith("/") ? parentPath + name : parentPath +
"/" + name;
+ }
+
+ Map<String, Object> properties = new HashMap<>();
+
+ // primary node type and mixins
+ String primaryType = getChildText(element, "primaryNodeType");
+ if (StringUtils.isNotBlank(primaryType) &&
!parserOptions.getIgnorePropertyNames().contains("jcr:primaryType")) {
+ properties.put("jcr:primaryType", primaryType);
+ }
+ String[] mixins = getChildTextArray(element, "mixinNodeType");
+ if (mixins.length > 0 &&
!parserOptions.getIgnorePropertyNames().contains("jcr:mixinTypes")) {
+ properties.put("jcr:mixinTypes", mixins);
+ }
+
+ // properties
+ List<Element> propertyElements = getChildren(element, "property");
+ for (Element propertyElement : propertyElements) {
+
+ // property name
+ String name = getChildText(propertyElement, "name");
+ if (StringUtils.isBlank(name)) {
+ throw new ParseException("Property without name detected at
path " + path);
+ }
+ if (parserOptions.getIgnorePropertyNames().contains(name)) {
+ continue;
+ }
+
+ // property type
+ String type = getChildText(propertyElement, "type");
+ if (StringUtils.isBlank(type)) {
+ throw new ParseException("Property '" + name + "' has no type
at path " + path);
+ }
+
+ // property value
+ Object value;
+ List<Element> valuesElements = getChildren(propertyElement,
"values");
+ if (!valuesElements.isEmpty()) {
+ Element valuesElement = valuesElements.get(0);
+ List<Element> valueElements = getChildren(valuesElement,
"value");
+ String[] stringValues = new String[valueElements.size()];
+ for (int i = 0; i < valueElements.size(); i++) {
+ stringValues[i] = valueElements.get(i).getTextContent();
+ }
+ value = convertMultiValue(stringValues, type);
+ } else {
+ String stringValue = getChildText(propertyElement, "value");
+ value = convertValue(stringValue, type);
+ }
+ properties.put(name, value);
+ }
+
+ String defaultPrimaryType = parserOptions.getDefaultPrimaryType();
+ if (defaultPrimaryType != null) {
+ if (!properties.containsKey(JCR_PRIMARY_TYPE)) {
+ properties.put(JCR_PRIMARY_TYPE, defaultPrimaryType);
+ }
+ }
+ handler.resource(path, properties);
+
+ // child nodes
+ List<Element> nodeElements = getChildren(element, "node");
+ for (Element node : nodeElements) {
+ parse(handler, node, parserOptions, path);
+ }
+
+ }
+
+ private List<Element> getChildren(Element element, String childName) {
+ List<Element> result = new ArrayList<>();
+ NodeList children = element.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ if (child instanceof Element) {
+ Element childElement = (Element) child;
+ if (StringUtils.equals(childElement.getNodeName(), childName))
{
+ result.add(childElement);
+ }
+ }
+ }
+ return result;
+ }
+
+ private String getChildText(Element element, String childName) {
+ List<Element> children = getChildren(element, childName);
+ if (children.isEmpty()) {
+ return null;
+ } else if (children.size() == 1) {
+ return children.get(0).getTextContent();
+ } else {
+ throw new ParseException("Found multiple elements with name '" +
childName + "': " + children.size());
+ }
+ }
+
+ private String[] getChildTextArray(Element element, String childName) {
+ List<Element> children = getChildren(element, childName);
+ String[] result = new String[children.size()];
+ for (int i = 0; i < children.size(); i++) {
+ result[i] = children.get(i).getTextContent();
+ }
+ return result;
+ }
+
+ private Object convertValue(String value, String type) {
+ switch (type) {
+ case "String":
+ case "Name":
+ case "Path":
+ case "Reference":
+ case "WeakReference":
+ case "URI":
+ return value;
+ case "Long":
+ return Long.valueOf(value);
+ case "Double":
+ return Double.valueOf(value);
+ case "Date":
+ return ParserHelper.parseDate(value);
+ case "Boolean":
+ return Boolean.valueOf(value);
+ case "Decimal":
+ return new BigDecimal(value);
+ default:
+ throw new ParseException(String.format("Unsupported property
type: %s.", type));
+ }
+ }
+
+ private Object convertMultiValue(String[] values, String type) {
+ Object[] result = new Object[values.length];
+ for (int i = 0; i < values.length; i++) {
+ result[i] = convertValue(values[i], type);
+ }
+ return ParserHelper.convertSingleTypeArray(result);
+ }
+
+}
diff --git
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
b/contentparser/org-apache-sling-contentparser-xml/src/test/java/org/apache/sling/contentparser/xml/internal/XmlContentParserTest.java
similarity index 69%
copy from
contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
copy to
contentparser/org-apache-sling-contentparser-xml/src/test/java/org/apache/sling/contentparser/xml/internal/XmlContentParserTest.java
index 3099ae8..111ac73 100644
---
a/contentparser/org-apache-sling-contentparser-json/src/test/java/org/apache/sling/contentparser/json/internal/JsonContentParserTest.java
+++
b/contentparser/org-apache-sling-contentparser-xml/src/test/java/org/apache/sling/contentparser/xml/internal/XmlContentParserTest.java
@@ -16,51 +16,50 @@
~ specific language governing permissions and limitations
~ under the License.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-package org.apache.sling.contentparser.json.internal;
+package org.apache.sling.contentparser.xml.internal;
import java.io.File;
import java.math.BigDecimal;
import java.util.Calendar;
-import java.util.EnumSet;
import java.util.Map;
import java.util.TimeZone;
import org.apache.sling.contentparser.api.ContentParser;
-import org.apache.sling.contentparser.api.JsonParserFeature;
import org.apache.sling.contentparser.api.ParseException;
import org.apache.sling.contentparser.api.ParserOptions;
-import org.apache.sling.contentparser.json.internal.mapsupport.ContentElement;
+import org.apache.sling.contentparser.testutils.mapsupport.ContentElement;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableSet;
-import static junit.framework.TestCase.assertNull;
+import static org.apache.sling.contentparser.testutils.TestUtils.parse;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
-public class JsonContentParserTest {
+public class XmlContentParserTest {
private File file;
- private ContentParser contentParser;
+ private ContentParser underTest;
@Before
public void setUp() {
- file = new File("src/test/resources/content-test/content.json");
- contentParser = new JsonContentParser();
+ file = new File("src/test/resources/content-test/content.xml");
+ underTest = new XmlContentParser();
}
@Test
public void testPageJcrPrimaryType() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, file);
+ ContentElement content = parse(underTest, file);
assertEquals("app:Page",
content.getProperties().get("jcr:primaryType"));
}
@Test
public void testDataTypes() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, file);
+ ContentElement content = parse(underTest, file);
Map<String, Object> props =
content.getChild("toolbar/profiles/jcr:content").getProperties();
assertEquals(true, props.get("hideInNav"));
@@ -76,7 +75,7 @@ public class JsonContentParserTest {
@Test
public void testContentProperties() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, file);
+ ContentElement content = parse(underTest, file);
Map<String, Object> props =
content.getChild("jcr:content/header").getProperties();
assertEquals("/content/dam/sample/header.png",
props.get("imageReference"));
@@ -84,7 +83,7 @@ public class JsonContentParserTest {
@Test
public void testCalendar() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, new
ParserOptions().detectCalendarValues(true), file);
+ ContentElement content = parse(underTest, new
ParserOptions().detectCalendarValues(true), file);
Map<String, Object> props =
content.getChild("jcr:content").getProperties();
@@ -103,26 +102,9 @@ public class JsonContentParserTest {
}
@Test
- public void testIso8601Calendar() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, new
ParserOptions().detectCalendarValues(true), file);
-
- Map<String, Object> props =
content.getChild("jcr:content").getProperties();
-
- Calendar calendar = (Calendar) props.get("dateISO8601String");
- assertNotNull(calendar);
-
- assertEquals(2014, calendar.get(Calendar.YEAR));
- assertEquals(4, calendar.get(Calendar.MONTH) + 1);
- assertEquals(22, calendar.get(Calendar.DAY_OF_MONTH));
-
- assertEquals(15, calendar.get(Calendar.HOUR_OF_DAY));
- assertEquals(11, calendar.get(Calendar.MINUTE));
- assertEquals(24, calendar.get(Calendar.SECOND));
- }
-
- @Test
public void testUTF8Chars() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, file);
+
+ ContentElement content = parse(underTest, file);
Map<String, Object> props =
content.getChild("jcr:content").getProperties();
@@ -132,23 +114,23 @@ public class JsonContentParserTest {
@Test(expected = ParseException.class)
public void testParseInvalidJson() throws Exception {
file = new File("src/test/resources/invalid-test/invalid.json");
- ContentElement content = TestUtils.parse(contentParser, file);
+
+ ContentElement content = parse(underTest, file);
assertNull(content);
}
@Test(expected = ParseException.class)
public void testParseInvalidJsonWithObjectList() throws Exception {
file = new
File("src/test/resources/invalid-test/contentWithObjectList.json");
- ContentElement content = TestUtils.parse(contentParser, file);
+
+ ContentElement content = parse(underTest, file);
assertNull(content);
}
@Test
public void testIgnoreResourcesProperties() throws Exception {
- ContentElement content = TestUtils.parse(
- contentParser,
- new
ParserOptions().ignoreResourceNames(ImmutableSet.of("header", "newslist",
"security:acl", "security:principals"))
- .ignorePropertyNames(ImmutableSet.of("jcr:title")),
file);
+ ContentElement content = parse(underTest, new
ParserOptions().ignoreResourceNames(ImmutableSet.of("header", "newslist"))
+ .ignorePropertyNames(ImmutableSet.of("jcr:title")), file);
ContentElement child = content.getChild("jcr:content");
assertEquals("Sample Homepage",
child.getProperties().get("pageTitle"));
@@ -164,7 +146,8 @@ public class JsonContentParserTest {
@Test
public void testGetChild() throws Exception {
- ContentElement content = TestUtils.parse(contentParser, file);
+
+ ContentElement content = parse(underTest, file);
assertNull(content.getName());
ContentElement deepChild =
content.getChild("jcr:content/par/image/file/jcr:content");
@@ -178,9 +161,4 @@ public class JsonContentParserTest {
assertNull(invalidChild);
}
- @Test(expected = ParseException.class)
- public void testFailsWithoutCommentsEnabled() throws Exception {
- TestUtils.parse(contentParser, new
ParserOptions().jsonParserFeatures(EnumSet.noneOf(JsonParserFeature.class)),
file);
- }
-
}
diff --git
a/contentparser/org-apache-sling-contentparser-xml/src/test/resources/content-test/content.xml
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/content-test/content.xml
new file mode 100644
index 0000000..6caed95
--- /dev/null
+++
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/content-test/content.xml
@@ -0,0 +1,334 @@
+<?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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<node>
+ <primaryNodeType>app:Page</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:32:59
GMT+0200</value><type>Date</type></property>
+
+ <node>
+ <name>jcr:content</name>
+ <primaryNodeType>app:PageContent</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:title</name><value>English</value><type>String</type></property>
+
<property><name>app:template</name><value>sample/templates/homepage</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:32:59
GMT+0200</value><type>Date</type></property>
+ <property><name>app:lastModified</name><value>Tue Apr 22 2014 15:11:24
GMT+0200</value><type>Date</type></property>
+
<property><name>dateISO8601String</name><value>2014-04-22T15:11:24.000+02:00</value><type>Date</type></property>
+ <property><name>pageTitle</name><value>Sample
Homepage</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/homepage</value><type>String</type></property>
+
<property><name>sling:resourceSuperType</name><value>sample/components/supertype</value><type>String</type></property>
+
<property><name>app:designPath</name><value>/etc/designs/sample</value><type>String</type></property>
+
<property><name>app:lastModifiedBy</name><value>admin</value><type>String</type></property>
+
<property><name>utf8Property</name><value>äöü߀</value><type>String</type></property>
+
<property><name>refpro1</name><value>abc</value><type>Reference</type></property>
+
<property><name>pathprop1</name><value>def</value><type>Path</type></property>
+
+ <node>
+ <name>par</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys</value><type>String</type></property>
+ <node>
+ <name>colctrl</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+
<property><name>layout</name><value>2;colctrl-lt0</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:02:24
GMT+0200</value><type>Date</type></property>
+ <property><name>jcr:lastModified</name><value>Mon Aug 23 2010 22:02:35
GMT+0200</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys/colctrl</value><type>String</type></property>
+ </node>
+ <node>
+ <name>image</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>fileReference</name><value>/content/dam/sample/portraits/jane_doe.jpg</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:03:39
GMT+0200</value><type>Date</type></property>
+
<property><name>width</name><value>340</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Sun Oct 31 2010 21:39:50
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceTyp</name><value>foundation/components/image</value><type>String</type></property>
+ <node>
+ <name>file</name>
+ <primaryNodeType>nt:file</primaryNodeType>
+
<property><name>jcr:createdB</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:32:59
GMT+0200</value><type>Date</type></property>
+ <node>
+ <name>jcr:content</name>
+ <primaryNodeType>nt:resource</primaryNodeType>
+
<property><name>jcr:lastModifiedBy</name><value>anonymous</value><type>String</type></property>
+
<property><name>jcr:mimeType</name><value>image/jpeg</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Thu Aug 07 2014
16:32:59 GMT+0200</value><type>Date</type></property>
+
<property><name>jcr:uuid</name><value>eda76d00-b2cd-4b59-878f-c33f71ceaddc</value><type>String</type></property>
+ </node>
+ </node>
+ </node>
+ <node>
+ <name>title_1</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:title</name><value>Strategic
Consulting</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:12:08
GMT+0200</value><type>Date</type></property>
+ <property><name>jcr:lastModified</name><value>Wed Oct 27 2010 21:33:24
GMT+0200</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/title</value><type>String</type></property>
+ </node>
+ <node>
+ <name>text_1</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Sun Oct 31 2010 21:48:04
GMT+0100</value><type>Date</type></property>
+ <property><name>text</name><value><![CDATA[<p><span
class="Apple-style-span" style="font-size: 12px;">In today's competitive
market, organizations can face several key geometric challenges:</span></p>
+<ul>
+<li><span class="Apple-style-span" style="font-size: 12px;">Polyhedral
Sectioning</span></li>
+<li><span class="Apple-style-span" style="font-size:
12px;">Triangulation </span></li>
+<li><span class="Apple-style-span" style="font-size: 12px;">Trigonometric
Calculation</span></li>
+<li><span class="Apple-style-span" style="font-size: 12px;">Ruler and Compass
Construction</span></li>
+</ul>
+<p><span class="Apple-style-span" style="font-size: 12px;"><br>
+Sample is ready to help your organization deal effectively with all these
challenges through our award winning geometric consulting services.</span></p>
+<p style="font-family: tahoma, arial, helvetica, sans-serif; font-size:
12px;\"><\/p>
+]]></value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Sun Oct 31 2010 21:49:06
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/text</value><type>String</type></property>
+
<property><name>textIsRich</name><value>true</value><type>String</type></property>
+ </node>
+ <node>
+ <name>col_break12825937554040</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>controlType</name><value>break</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys/colctrl</value><type>String</type></property>
+ </node>
+ <node>
+ <name>image_0</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>fileReference</name><value>/content/dam/sample/offices/clean_room.jpg</value><type>String</type></property>
+
<property><name>height</name><value>226</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:04:46
GMT+0200</value><type>Date</type></property>
+ <property><name>jcr:lastModified</name><value>Fri Nov 05 2010 10:38:15
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/image</value><type>String</type></property>
+
<property><name>imageRotate</name><value>0</value><type>String</type></property>
+ <node>
+ <name>file</name>
+ <primaryNodeType>nt:file</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:32:59
GMT+0200</value><type>Date</type></property>
+ <node>
+ <name>jcr:content</name>
+ <primaryNodeType>nt:resource</primaryNodeType>
+
<property><name>jcr:lastModifiedBy</name><value>anonymous</value><type>String</type></property>
+
<property><name>jcr:mimeType</name><value>image/jpeg</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Thu Aug 07 2014
16:32:59 GMT+0200</value><type>String</type></property>
+
<property><name>jcr:uuid</name><value>6139077f-191f-4337-aaef-55456ebe6784</value><type>String</type></property>
+ </node>
+ </node>
+ </node>
+ <node>
+ <name>title_2</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:title</name><value>Shape
Technology</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:12:13
GMT+0200</value><type>Date</type></property>
+ <property><name>jcr:lastModified</name><value>Tue Oct 26 2010 21:16:29
GMT+0200</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/title</value><type>String</type></property>
+ </node>
+ <node>
+ <name>text_0</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Mon Aug 23 2010 22:16:30
GMT+0200</value><type>Date</type></property>
+ <property><name>text</name><value><![CDATA[<p>The Sample investment in
R&D has done more than solidify our industry leadership role, we have now
outpaced our competitors to such an extent that we are in an altogether new
space.</p>
+<p>This is why our high quality polygons and polyhedra provide the only
turnkey solutions across the whole range of euclidean geometry. And our
mathematicians are working on the next generation of fractal curves to bring
you shapes that are unthinkable today.</p>
+<p></p>
+<p></p>
+]]></value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Mon Nov 08 2010 20:39:00
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/text</value><type>String</type></property>
+
<property><name>textIsRich</name><value>true</value><type>String</type></property>
+ </node>
+ <node>
+ <name>col_end12825937444810</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>controlType</name><value>end</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys/colctrl</value><type>String</type></property>
+ </node>
+ </node>
+ <node>
+ <name>header</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+ <property><name>jcr:title</name><value>trust our experience
+to manage your business</value><type>String</type></property>
+
<property><name>imageReference</name><value>/content/dam/sample/header.png</value><type>String</type></property>
+ <property><name>text</name><value>Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Nunc eget neque. Nunc condimentum ipsum et orci.
Aenean est. Cras eget diam. read more</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/header</value><type>String</type></property>
+ </node>
+ <node>
+ <name>newslist</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+ <property><name>headline</name><value>trust our experience
+to manage your business</value><type>String</type></property>
+ <property><name>text</name><value>Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Nunc eget neque. Nunc condimentum ipsum et orci.
Aenean est. Cras eget diam. read more</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/listchildren</value><type>String</type></property>
+
<property><name>listroot</name><value>/content/sample/en/about/news</value><type>String</type></property>
+ </node>
+ <node>
+ <name>lead</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+ <property><name>jcr:title</name><value>World Leader in Applied Geometry
</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>text</name><value>Lead
Text</value><type>String</type></property>
+ <property><name>title</name><value>Lead
Title</value><type>String</type></property>
+ <property><name>jcr:description</name><value>ample has been selling and
servicing shapes for over 2000 years. From our beginnings as a small vendor of
squares and rectangles we have grown our business into a leading global
provider of platonic solids and fractals. Join us as we lead geometry into the
future.</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Wed Jan 19 2011 14:35:29
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/lead</value><type>String</type></property>
+ <node>
+ <name>app:annotations</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+ </node>
+ </node>
+ <node>
+ <name>image</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Wed Oct 27 2010 21:30:59
GMT+0200</value><type>Date</type></property>
+
<property><name>imageRotate</name><value>0</value><type>String</type></property>
+ </node>
+ <node>
+ <name>carousel</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>playSpeed</name><value>6000</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+
<property><name>pages</name><values><value>/content/sample/en/events/techsummit</value><value>/content/sample/en/events/userconf</value><value>/content/sample/en/events/shapecon</value><value>/content/sample/en/events/dsc</value></values><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Tue Oct 05 2010 14:14:27
GMT+0200</value><type>Date</type></property>
+
<property><name>transTime</name><value>1000</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>foundation/components/carousel</value><type>String</type></property>
+
<property><name>listFrom</name><value>static</value><type>String</type></property>
+ </node>
+ <node>
+ <name>rightpar</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys</value><type>String</type></property>
+ <node>
+ <name>teaser</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Tue Jan 25 2011 11:30:09
GMT+0100</value><type>Date</type></property>
+
<property><name>campaignpath</name><value>/content/campaigns/sample</value><type>String</type></property>
+ <property><name>jcr:lastModified</name><value>Wed Feb 02 2011 08:40:30
GMT+0100</value><type>Date</type></property>
+
<property><name>sling:resourceTyp</name><value>personalization/components/teaser</value><type>String</type></property>
+ </node>
+ </node>
+ </node>
+ <node>
+ <name>toolbar</name>
+ <primaryNodeType>app:Page</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:33:00
GMT+0200</value><type>String</type></property>
+ <node>
+ <name>jcr:content</name>
+ <primaryNodeType>app:PageContent</primaryNodeType>
+ <property><name>subtitle</name><value>Contains the
toolbar</value><type>String</type></property>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:title</name><value>Toolbar</value><type>String</type></property>
+
<property><name>app:template</name><value>sample/templates/contentpage</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:33:00
GMT+0200</value><type>String</type></property>
+ <property><name>app:lastModified</name><value>Wed Aug 25 2010 22:51:02
GMT+0200</value><type>Date</type></property>
+
<property><name>hideInNav</name><value>true</value><type>Date</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/contentpage</value><type>String</type></property>
+
<property><name>app:lastModifiedBy</name><value>admin</value><type>String</type></property>
+ <node>
+ <name>par</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys</value><type>String</type></property>
+ </node>
+ <node>
+ <name>rightpar</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/iparsys</value><type>String</type></property>
+ <node>
+ <name>iparsys_fake_par</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/iparsys/par</value><type>String</type></property>
+ </node>
+ </node>
+ </node>
+ <node>
+ <name>profiles</name>
+ <primaryNodeType>app:Page</primaryNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:33:00
GMT+0200</value><type>Date</type></property>
+ <node>
+ <name>jcr:content</name>
+ <primaryNodeType>app:PageContent</primaryNodeType>
+ <mixinNodeType>type1</mixinNodeType>
+ <mixinNodeType>type2</mixinNodeType>
+
<property><name>jcr:createdBy</name><value>admin</value><type>String</type></property>
+
<property><name>jcr:title</name><value>Profiles</value><type>String</type></property>
+
<property><name>app:template</name><value>sample/templates/contentpage</value><type>String</type></property>
+ <property><name>jcr:created</name><value>Thu Aug 07 2014 16:33:00
GMT+0200</value><type>Date</type></property>
+ <property><name>app:lastModified</name><value>Thu Nov 05 2009 20:27:13
GMT+0100</value><type>Date</type></property>
+
<property><name>hideInNav</name><value>true</value><type>Boolean</type></property>
+
<property><name>sling:resourceType</name><value>sample/components/contentpage</value><type>String</type></property>
+
<property><name>app:lastModifiedBy</name><value>admin</value><type>String</type></property>
+
<property><name>longProp</name><value>1234567890123</value><type>Long</type></property>
+
<property><name>decimalProp</name><value>1.2345</value><type>Decimal</type></property>
+
<property><name>booleanProp</name><value>true</value><type>Boolean</type></property>
+
<property><name>longPropMulti</name><values><value>1234567890123</value><value>55</value></values><type>Long</type></property>
+
<property><name>decimalPropMulti</name><values><value>1.2345</value><value>1.1</value></values><type>Decimal</type></property>
+
<property><name>booleanPropMulti</name><values><value>true</value><value>false</value></values><type>Boolean</type></property>
+
<property><name>stringPropMulti</name><values><value>aa</value><value>bb</value><value>cc</value></values><type>String</type></property>
+ <node>
+ <name>par</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/parsys</value><type>String</type></property>
+ <node>
+ <name>textimage</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/textimage</value><type>String</type></property>
+ </node>
+ <node>
+ <name>mygadgets</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>gadgets</name><value>http://customer.meteogroup.de/meteogroup/gadgets/wetter24.xml
+http://germanweatherradar.googlecode.com/svn/trunk/german-weather-radar.xml
+http://www.digitalpowered.info/gadget/ski.pictures.xml
+http://www.canbuffi.de/gadgets/clock/clock.xml</value><type>String</type></property>
+
<property><name>sling:resourceType</name><value>personalization/components/mygadgets</value><type>String</type></property>
+ </node>
+ </node>
+ <node>
+ <name>rightpar</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/iparsys</value><type>String</type></property>
+ <node>
+ <name>iparsys_fake_par</name>
+ <primaryNodeType>nt:unstructured</primaryNodeType>
+
<property><name>sling:resourceType</name><value>foundation/components/iparsys/par</value><type>String</type></property>
+ </node>
+ </node>
+ </node>
+ </node>
+ </node>
+</node>
diff --git
a/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/contentWithObjectList.json
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/contentWithObjectList.json
new file mode 100644
index 0000000..e4527a0
--- /dev/null
+++
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/contentWithObjectList.json
@@ -0,0 +1,14 @@
+{
+ "prop1": "value1",
+ "childObject": {
+ "prop2": "value2"
+ },
+ "childObjectList": [
+ {
+ "prop1": "value1"
+ },
+ {
+ "prop2": "value2"
+ }
+ ]
+}
diff --git
a/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/invalid.json
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/invalid.json
new file mode 100644
index 0000000..59fc86c
--- /dev/null
+++
b/contentparser/org-apache-sling-contentparser-xml/src/test/resources/invalid-test/invalid.json
@@ -0,0 +1 @@
+This is invalid json.
diff --git a/contentparser/pom.xml b/contentparser/pom.xml
new file mode 100644
index 0000000..9b5dd03
--- /dev/null
+++ b/contentparser/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ 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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>35</version>
+ <relativePath/>
+ </parent>
+
+ <artifactId>org.apache.sling.contentparser.reactor</artifactId>
+ <packaging>pom</packaging>
+ <version>0.9.0-SNAPSHOT</version>
+
+ <name>Apache Sling Content Parser Reactor</name>
+
+ <modules>
+ <module>org-apache-sling-contentparser-api</module>
+ <module>org-apache-sling-contentparser-json</module>
+ <module>org-apache-sling-contentparser-xml</module>
+ <module>org-apache-sling-contentparser-testutils</module>
+ </modules>
+</project>