--- /dev/null
+package org.simantics.scl.data.xml;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.io.StringReader;\r
+import java.io.StringWriter;\r
+import java.net.URL;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.LinkedHashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.jdom2.Document;\r
+import org.jdom2.Element;\r
+import org.jdom2.IllegalAddException;\r
+import org.jdom2.JDOMException;\r
+import org.jdom2.Namespace;\r
+import org.jdom2.filter.Filters;\r
+import org.jdom2.input.SAXBuilder;\r
+import org.jdom2.input.sax.XMLReaderJDOMFactory;\r
+import org.jdom2.input.sax.XMLReaderXSDFactory;\r
+import org.jdom2.output.Format;\r
+import org.jdom2.output.XMLOutputter;\r
+import org.jdom2.xpath.XPathExpression;\r
+import org.jdom2.xpath.XPathFactory;\r
+import org.simantics.scl.runtime.function.Function;\r
+import org.simantics.scl.runtime.function.FunctionImpl1;\r
+import org.simantics.scl.runtime.reporting.SCLReporting;\r
+\r
+public class JDomHelper {\r
+ private static final SAXBuilder BUILDER = new SAXBuilder();\r
+ private static final XMLOutputter OUTPUTTER = new XMLOutputter(Format.getPrettyFormat());\r
+ private static final XPathFactory XPATH_FACTORY = XPathFactory.instance(); \r
+ \r
+ private static final int XPATH_CACHE_MAX = 50;\r
+ \r
+ private static final Map<String,XPathExpression<Element>> XPATH_CACHE = Collections.synchronizedMap(\r
+ new LinkedHashMap<String,XPathExpression<Element>>(XPATH_CACHE_MAX) {\r
+ private static final long serialVersionUID = 2546245625L;\r
+ \r
+ @Override\r
+ protected boolean removeEldestEntry(Map.Entry<String,XPathExpression<Element>> eldest) {\r
+ return size() > XPATH_CACHE_MAX;\r
+ }\r
+ });\r
+\r
+ public static Document parseString(String xmlDocument) throws JDOMException, IOException {\r
+ return BUILDER.build(new StringReader(xmlDocument));\r
+ }\r
+ \r
+ public static Document parseFile(String xmlFileName) throws JDOMException, IOException {\r
+ return BUILDER.build(new File(xmlFileName));\r
+ }\r
+ \r
+ public static String outputString(Document document) throws IOException {\r
+ StringWriter writer = new StringWriter();\r
+ OUTPUTTER.output(document, writer);\r
+ return writer.toString();\r
+ }\r
+ \r
+ private static XPathExpression<Element> getXPathExpression(String xPathText) {\r
+ XPathExpression<Element> expression = XPATH_CACHE.get(xPathText);\r
+ if(expression == null) {\r
+ expression = XPATH_FACTORY.compile(xPathText, Filters.element());\r
+ XPATH_CACHE.put(xPathText, expression);\r
+ }\r
+ return expression;\r
+ }\r
+ \r
+ public static List<Element> elementsByXPath(Element element, String xPathText) {\r
+ XPathExpression<Element> expr = getXPathExpression(xPathText);\r
+ return expr.evaluate(element);\r
+ }\r
+ \r
+ public static void addNamedChild(Element parent, String name, Element child) {\r
+ child.setName(name);\r
+ try {\r
+ parent.addContent(child);\r
+ } catch(IllegalAddException e) {\r
+ SCLReporting.printError("Failed to set the parent of an element " + name + ":");\r
+ SCLReporting.printError(" " + e.getMessage());\r
+ }\r
+ }\r
+ \r
+ public static void setNamespace(Document document, String namespace) {\r
+ setElementNamespace(document.getRootElement(), namespace);\r
+ }\r
+ \r
+ public static void setElementNamespace(Element element, String namespace) {\r
+ Namespace ns = Namespace.getNamespace(namespace);\r
+ setNamespaceRecursively(element, ns);\r
+ } \r
+\r
+ private static void setNamespaceRecursively(Element element, Namespace ns) {\r
+ element.setNamespace(ns);\r
+ for(Element child : element.getChildren())\r
+ if(child.getNamespace() == Namespace.NO_NAMESPACE)\r
+ setNamespaceRecursively(child, ns);\r
+ }\r
+ \r
+ public static void clearNamespace(Document document) {\r
+ clearElementNamespace(document.getRootElement());\r
+ }\r
+ \r
+ public static void clearElementNamespace(Element element) {\r
+ element.setNamespace(null);\r
+ for (Element child : element.getChildren())\r
+ clearElementNamespace(child);\r
+ }\r
+ \r
+ public static Function parseStringWithSchemaFile(String xsdFile) throws JDOMException {\r
+ XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));\r
+ SAXBuilder builder = new SAXBuilder(factory);\r
+ return parseStringWithBuilder(builder);\r
+ }\r
+ \r
+ public static Function parseStringWithSchemaURL(URL xsd) throws JDOMException {\r
+ XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);\r
+ SAXBuilder builder = new SAXBuilder(factory);\r
+ return parseStringWithBuilder(builder);\r
+ }\r
+ \r
+ public static Function parseFileWithSchemaFile(String xsdFile) throws JDOMException {\r
+ XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));\r
+ SAXBuilder builder = new SAXBuilder(factory);\r
+ return parseFileWithBuilder(builder);\r
+ }\r
+ \r
+ public static Function parseFileWithSchemaURL(URL xsd) throws JDOMException {\r
+ XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);\r
+ SAXBuilder builder = new SAXBuilder(factory);\r
+ return parseFileWithBuilder(builder);\r
+ }\r
+ \r
+ private static Function parseStringWithBuilder(final SAXBuilder builder) {\r
+ return new FunctionImpl1<String, Document>() {\r
+ @Override\r
+ public Document apply(String xml) {\r
+ try {\r
+ return builder.build(new StringReader(xml));\r
+ }\r
+ catch (JDOMException | IOException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ };\r
+ };\r
+ }\r
+ \r
+ private static Function parseFileWithBuilder(final SAXBuilder builder) {\r
+ return new FunctionImpl1<String, Document>() {\r
+ @Override\r
+ public Document apply(String xml) {\r
+ try {\r
+ return builder.build(new File(xml));\r
+ }\r
+ catch (JDOMException | IOException e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ };\r
+ };\r
+ }\r
+ \r
+ public static void sortChildrenWith(final Function comparator, Element element) {\r
+ element.sortChildren(new Comparator() {\r
+ @Override\r
+ public int compare(Object o1, Object o2) {\r
+ return (Integer)comparator.apply(o1, o2);\r
+ }\r
+ });\r
+ }\r
+}\r