1 package org.simantics.scl.data.xml;
\r
4 import java.io.IOException;
\r
5 import java.io.StringReader;
\r
6 import java.io.StringWriter;
\r
8 import java.util.Collections;
\r
9 import java.util.Comparator;
\r
10 import java.util.LinkedHashMap;
\r
11 import java.util.List;
\r
12 import java.util.Map;
\r
14 import org.jdom2.Document;
\r
15 import org.jdom2.Element;
\r
16 import org.jdom2.IllegalAddException;
\r
17 import org.jdom2.JDOMException;
\r
18 import org.jdom2.Namespace;
\r
19 import org.jdom2.filter.Filters;
\r
20 import org.jdom2.input.SAXBuilder;
\r
21 import org.jdom2.input.sax.XMLReaderJDOMFactory;
\r
22 import org.jdom2.input.sax.XMLReaderXSDFactory;
\r
23 import org.jdom2.output.Format;
\r
24 import org.jdom2.output.XMLOutputter;
\r
25 import org.jdom2.xpath.XPathExpression;
\r
26 import org.jdom2.xpath.XPathFactory;
\r
27 import org.simantics.scl.runtime.function.Function;
\r
28 import org.simantics.scl.runtime.function.FunctionImpl1;
\r
29 import org.simantics.scl.runtime.reporting.SCLReporting;
\r
31 public class JDomHelper {
\r
32 private static final SAXBuilder BUILDER = new SAXBuilder();
\r
33 private static final XMLOutputter OUTPUTTER = new XMLOutputter(Format.getPrettyFormat());
\r
34 private static final XPathFactory XPATH_FACTORY = XPathFactory.instance();
\r
36 private static final int XPATH_CACHE_MAX = 50;
\r
38 private static final Map<String,XPathExpression<Element>> XPATH_CACHE = Collections.synchronizedMap(
\r
39 new LinkedHashMap<String,XPathExpression<Element>>(XPATH_CACHE_MAX) {
\r
40 private static final long serialVersionUID = 2546245625L;
\r
43 protected boolean removeEldestEntry(Map.Entry<String,XPathExpression<Element>> eldest) {
\r
44 return size() > XPATH_CACHE_MAX;
\r
48 public static Document parseString(String xmlDocument) throws JDOMException, IOException {
\r
49 return BUILDER.build(new StringReader(xmlDocument));
\r
52 public static Document parseFile(String xmlFileName) throws JDOMException, IOException {
\r
53 return BUILDER.build(new File(xmlFileName));
\r
56 public static String outputString(Document document) throws IOException {
\r
57 StringWriter writer = new StringWriter();
\r
58 OUTPUTTER.output(document, writer);
\r
59 return writer.toString();
\r
62 private static XPathExpression<Element> getXPathExpression(String xPathText) {
\r
63 XPathExpression<Element> expression = XPATH_CACHE.get(xPathText);
\r
64 if(expression == null) {
\r
65 expression = XPATH_FACTORY.compile(xPathText, Filters.element());
\r
66 XPATH_CACHE.put(xPathText, expression);
\r
71 public static List<Element> elementsByXPath(Element element, String xPathText) {
\r
72 XPathExpression<Element> expr = getXPathExpression(xPathText);
\r
73 return expr.evaluate(element);
\r
76 public static void addNamedChild(Element parent, String name, Element child) {
\r
77 child.setName(name);
\r
79 parent.addContent(child);
\r
80 } catch(IllegalAddException e) {
\r
81 SCLReporting.printError("Failed to set the parent of an element " + name + ":");
\r
82 SCLReporting.printError(" " + e.getMessage());
\r
86 public static void setNamespace(Document document, String namespace) {
\r
87 setElementNamespace(document.getRootElement(), namespace);
\r
90 public static void setElementNamespace(Element element, String namespace) {
\r
91 Namespace ns = Namespace.getNamespace(namespace);
\r
92 setNamespaceRecursively(element, ns);
\r
95 private static void setNamespaceRecursively(Element element, Namespace ns) {
\r
96 element.setNamespace(ns);
\r
97 for(Element child : element.getChildren())
\r
98 if(child.getNamespace() == Namespace.NO_NAMESPACE)
\r
99 setNamespaceRecursively(child, ns);
\r
102 public static void clearNamespace(Document document) {
\r
103 clearElementNamespace(document.getRootElement());
\r
106 public static void clearElementNamespace(Element element) {
\r
107 element.setNamespace(null);
\r
108 for (Element child : element.getChildren())
\r
109 clearElementNamespace(child);
\r
112 public static Function parseStringWithSchemaFile(String xsdFile) throws JDOMException {
\r
113 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));
\r
114 SAXBuilder builder = new SAXBuilder(factory);
\r
115 return parseStringWithBuilder(builder);
\r
118 public static Function parseStringWithSchemaURL(URL xsd) throws JDOMException {
\r
119 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);
\r
120 SAXBuilder builder = new SAXBuilder(factory);
\r
121 return parseStringWithBuilder(builder);
\r
124 public static Function parseFileWithSchemaFile(String xsdFile) throws JDOMException {
\r
125 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));
\r
126 SAXBuilder builder = new SAXBuilder(factory);
\r
127 return parseFileWithBuilder(builder);
\r
130 public static Function parseFileWithSchemaURL(URL xsd) throws JDOMException {
\r
131 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);
\r
132 SAXBuilder builder = new SAXBuilder(factory);
\r
133 return parseFileWithBuilder(builder);
\r
136 private static Function parseStringWithBuilder(final SAXBuilder builder) {
\r
137 return new FunctionImpl1<String, Document>() {
\r
139 public Document apply(String xml) {
\r
141 return builder.build(new StringReader(xml));
\r
143 catch (JDOMException | IOException e) {
\r
144 throw new RuntimeException(e);
\r
150 private static Function parseFileWithBuilder(final SAXBuilder builder) {
\r
151 return new FunctionImpl1<String, Document>() {
\r
153 public Document apply(String xml) {
\r
155 return builder.build(new File(xml));
\r
157 catch (JDOMException | IOException e) {
\r
158 throw new RuntimeException(e);
\r
164 public static void sortChildrenWith(final Function comparator, Element element) {
\r
165 element.sortChildren(new Comparator() {
\r
167 public int compare(Object o1, Object o2) {
\r
168 return (Integer)comparator.apply(o1, o2);
\r