+ private void writeXmlNode(final Node node) throws IOException {
+ if (isArrayElement(node)) {
+ writeArrayContent(node);
+ return;
+ }
+ final Element firstChildElement = getFirstChildElement(node);
+ if (firstChildElement == null) {
+ writeXmlValue(node);
+ } else {
+ writeObjectContent(firstChildElement);
+ }
+ }
+
+ private void writeArrayContent(final Node node) throws IOException {
+ writer.beginArray();
+ handleArray(node);
+ writer.endArray();
+ }
+
+ private void writeObjectContent(final Element firstChildElement) throws IOException {
+ writer.beginObject();
+ writeObject(firstChildElement);
+ writer.endObject();
+ }
+
+ private static boolean isArrayElement(final Node node) {
+ if (ELEMENT_NODE == node.getNodeType()) {
+ final String nodeName = node.getNodeName();
+ for (Node nextNode = node.getNextSibling(); nextNode != null; nextNode = nextNode.getNextSibling()) {
+ if (ELEMENT_NODE == nextNode.getNodeType() && nodeName.equals(nextNode.getNodeName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void handleArray(final Node node) throws IOException {
+ final Element parentNode = (Element)node.getParentNode();
+ final NodeList elementsList = parentNode.getElementsByTagName(node.getNodeName());
+ for (int i = 0, length = elementsList.getLength(); i < length; i++) {
+ final Node arrayElement = elementsList.item(i);
+ final Element parent = (Element)arrayElement.getParentNode();
+ if (parentNode.isSameNode(parent)) {
+ final Element firstChildElement = getFirstChildElement(arrayElement);
+ if (firstChildElement != null) {
+ writeObjectContent(firstChildElement);
+ } else {
+ // It may be scalar
+ writeXmlValue(arrayElement);
+ }
+ }
+ }
+ }
+
+ private void writeObject(Node node) throws IOException {
+ String previousNodeName = "";
+ while (node != null) {
+ if (ELEMENT_NODE == node.getNodeType()) {
+ if (!node.getNodeName().equals(previousNodeName)) {
+ previousNodeName = node.getNodeName();
+ writer.name(node.getNodeName());
+ writeXmlNode(node);
+ }
+ }
+ node = node.getNextSibling();
+ }
+ }
+
+ private void writeXmlValue(final Node node) throws IOException {
+ Text firstChild = getFirstChildText(node);
+ String childNodeText = firstChild != null ? firstChild.getWholeText() : "";
+ childNodeText = childNodeText != null ? childNodeText.trim() : "";
+
+ if (NUMBER_PATTERN.matcher(childNodeText).matches()) {
+ writer.value(parseNumber(childNodeText));
+ return;
+ }
+ switch (childNodeText) {
+ case "null":
+ writer.nullValue();
+ break;
+ case "false":
+ writer.value(false);
+ break;
+ case "true":
+ writer.value(true);
+ break;
+ default:
+ writer.value(childNodeText);
+ }
+ }
+
+ private static Element getFirstChildElement(final Node node) {
+ final NodeList children = node.getChildNodes();
+ for (int i = 0, length = children.getLength(); i < length; i++) {
+ final Node childNode = children.item(i);
+ if (ELEMENT_NODE == childNode.getNodeType()) {
+ return (Element) childNode;
+ }
+ }
+ return null;
+ }
+
+ private static Text getFirstChildText(final Node node) {
+ final NodeList children = node.getChildNodes();
+ for (int i = 0, length = children.getLength(); i < length; i++) {
+ final Node childNode = children.item(i);
+ if (TEXT_NODE == childNode.getNodeType()) {
+ return (Text) childNode;
+ }
+ }
+ return null;
+ }
+
+ // json numbers are 64 bit wide floating point numbers - in java terms it is either long or double
+ private static Number parseNumber(final String numberText) {
+ if (NOT_DECIMAL_NUMBER_PATTERN.matcher(numberText).matches()) {
+ return Long.valueOf(numberText);
+ }
+
+ return Double.valueOf(numberText);
+ }