aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/zwobble')
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/ElementName.java8
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/SimpleSax.java54
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/SimpleSaxHandler.java9
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/XmlElement.java30
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/XmlElementBuilder.java25
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/XmlNode.java5
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/XmlParser.java54
-rw-r--r--src/main/java/org/zwobble/mammoth/xml/XmlTextNode.java8
8 files changed, 193 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/mammoth/xml/ElementName.java b/src/main/java/org/zwobble/mammoth/xml/ElementName.java
new file mode 100644
index 0000000..1d70c36
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/ElementName.java
@@ -0,0 +1,8 @@
+package org.zwobble.mammoth.xml;
+
+import lombok.Value;
+
+@Value
+public class ElementName {
+ private String localName;
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/SimpleSax.java b/src/main/java/org/zwobble/mammoth/xml/SimpleSax.java
new file mode 100644
index 0000000..8165552
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/SimpleSax.java
@@ -0,0 +1,54 @@
+package org.zwobble.mammoth.xml;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.stream.IntStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import static java.util.stream.Collectors.toMap;
+
+import lombok.val;
+
+public class SimpleSax {
+ public static void parseString(String value, SimpleSaxHandler handler) {
+ val parserFactory = SAXParserFactory.newInstance();
+ parserFactory.setNamespaceAware(true);
+ try {
+ val saxParser = parserFactory.newSAXParser();
+ val xmlReader = saxParser.getXMLReader();
+ xmlReader.setContentHandler(new DefaultHandler() {
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ final ElementName name = new ElementName(localName);
+ val attributesMap = IntStream.range(0, attributes.getLength())
+ .boxed()
+ .collect(toMap(
+ index -> new ElementName(attributes.getLocalName(index)),
+ attributes::getValue
+ ));
+ handler.startElement(name, attributesMap);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ handler.endElement();
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ handler.characters(new String(ch, start, length));
+ }
+ });
+ xmlReader.parse(new InputSource(new StringReader(value)));
+ } catch (ParserConfigurationException | SAXException | IOException exception) {
+ throw new RuntimeException(exception);
+ }
+ }
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/SimpleSaxHandler.java b/src/main/java/org/zwobble/mammoth/xml/SimpleSaxHandler.java
new file mode 100644
index 0000000..f56a940
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/SimpleSaxHandler.java
@@ -0,0 +1,9 @@
+package org.zwobble.mammoth.xml;
+
+import java.util.Map;
+
+public interface SimpleSaxHandler {
+ void startElement(ElementName name, Map<ElementName, String> attributes);
+ void endElement();
+ void characters(String string);
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlElement.java b/src/main/java/org/zwobble/mammoth/xml/XmlElement.java
new file mode 100644
index 0000000..a49f5f8
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/XmlElement.java
@@ -0,0 +1,30 @@
+package org.zwobble.mammoth.xml;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+
+@RequiredArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class XmlElement implements XmlNode {
+ public XmlElement(String name) {
+ this(name, ImmutableMap.of());
+ }
+
+ public XmlElement(String name, Map<String, String> attributes) {
+ this(name, attributes, ImmutableList.of());
+ }
+
+ @Getter
+ private final String name;
+ private final Map<String, String> attributes;
+ private final List<XmlNode> children;
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlElementBuilder.java b/src/main/java/org/zwobble/mammoth/xml/XmlElementBuilder.java
new file mode 100644
index 0000000..16b4865
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/XmlElementBuilder.java
@@ -0,0 +1,25 @@
+package org.zwobble.mammoth.xml;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+class XmlElementBuilder {
+ private final String name;
+ private final Map<String, String> attributes;
+ private final List<XmlNode> children;
+
+ XmlElementBuilder(String name, Map<String, String> attributes) {
+ this.name = name;
+ this.attributes = attributes;
+ this.children = new ArrayList<>();
+ }
+
+ XmlElement build() {
+ return new XmlElement(name, attributes, children);
+ }
+
+ void addChild(XmlNode node) {
+ children.add(node);
+ }
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlNode.java b/src/main/java/org/zwobble/mammoth/xml/XmlNode.java
new file mode 100644
index 0000000..c91e100
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/XmlNode.java
@@ -0,0 +1,5 @@
+package org.zwobble.mammoth.xml;
+
+public interface XmlNode {
+
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlParser.java b/src/main/java/org/zwobble/mammoth/xml/XmlParser.java
new file mode 100644
index 0000000..360c174
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/XmlParser.java
@@ -0,0 +1,54 @@
+package org.zwobble.mammoth.xml;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Map;
+
+import static java.util.stream.Collectors.toMap;
+
+import lombok.val;
+
+public class XmlParser {
+ public static XmlElement parseString(String value) {
+ val nodeGenerator = new NodeGenerator();
+ SimpleSax.parseString(value, nodeGenerator);
+ return nodeGenerator.getRoot();
+ }
+
+ private static class NodeGenerator implements SimpleSaxHandler {
+ private final Deque<XmlElementBuilder> elementStack;
+
+ public NodeGenerator() {
+ elementStack = new ArrayDeque<>();
+ }
+
+ public XmlElement getRoot() {
+ return elementStack.getFirst().build();
+ }
+
+ @Override
+ public void startElement(ElementName name, Map<ElementName, String> attributes) {
+ val simpleAttributes = attributes
+ .entrySet()
+ .stream()
+ .collect(toMap(
+ entry -> entry.getKey().getLocalName(),
+ entry -> entry.getValue()));
+ val element = new XmlElementBuilder(name.getLocalName(), simpleAttributes);
+ elementStack.add(element);
+ }
+
+ @Override
+ public void endElement() {
+ if (elementStack.size() > 1) {
+ val element = elementStack.removeLast();
+ elementStack.getLast().addChild(element.build());
+ }
+ }
+
+ @Override
+ public void characters(String string) {
+ elementStack.getLast().addChild(new XmlTextNode(string));
+ }
+ }
+}
diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlTextNode.java b/src/main/java/org/zwobble/mammoth/xml/XmlTextNode.java
new file mode 100644
index 0000000..0d63273
--- /dev/null
+++ b/src/main/java/org/zwobble/mammoth/xml/XmlTextNode.java
@@ -0,0 +1,8 @@
+package org.zwobble.mammoth.xml;
+
+import lombok.Value;
+
+@Value
+public class XmlTextNode implements XmlNode {
+ private String value;
+}