net.oneandone.sushi.xml.Selector Maven / Gradle / Ivy
/**
* Copyright 1&1 Internet AG, https://github.com/1and1/
*
* Licensed 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 net.oneandone.sushi.xml;
import net.oneandone.sushi.fs.Filesystem;
import net.oneandone.sushi.util.Strings;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Selector {
private final XPathFactory factory;
private final Map simples;
private final Map normals;
private NamespaceContext namespaceContext;
public Selector() {
this.factory = XPathFactory.newInstance();
this.simples = new HashMap();
this.normals = new HashMap();
this.namespaceContext = null;
}
public void setNamespaceContext(NamespaceContext namespaceContext) {
this.namespaceContext = namespaceContext;
}
//--
public List nodes(Node context, String path) {
if (context instanceof Element && isSimple(path)) {
return (List) nodesSimple((Element) context, path);
} else {
return nodesNormal(context, path);
}
}
public Node node(Node context, String xpath) {
List result;
result = nodes(context, xpath);
if (result.size() == 0) {
return null;
} else {
return result.get(0);
}
}
public List elements(Node root, String path) {
return (List) nodes(root, path);
}
public Element element(Node root, String path) throws XmlException {
Element element;
element = elementOpt(root, path);
if (element == null) {
throw new XmlException("element not found: " + path);
}
return element;
}
public Element elementOpt(Node root, String path) throws XmlException {
Node node;
node = node(root, path);
if (node == null) {
return null;
} else if (node instanceof Element) {
return (Element) node;
} else {
throw new XmlException("element expected: " + path);
}
}
public int integer(Node element, String path) throws XmlException {
String str;
str = string(element, path);
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
throw new XmlException("number expected node " + path + ": " + str);
}
}
/** Checkstyle rejects method name long_ */
public long longer(Node element, String path) throws XmlException {
String str;
str = string(element, path);
try {
return Long.parseLong(str);
} catch (NumberFormatException e) {
throw new XmlException("number expected node " + path + ": " + str);
}
}
public String string(Node ele, String path) throws XmlException {
String str;
str = stringOpt(ele, path);
if (str == null) {
throw new XmlException("no such node: " + path);
}
return str;
}
public String stringOpt(Node ele, String path) throws XmlException {
List lst;
lst = nodes(ele, path);
switch (lst.size()) {
case 0:
return null;
case 1:
return Dom.getString(lst.get(0));
default:
throw new XmlException("node ambiguous: " + path);
}
}
//--
public List nodesSimple(Element context, String path) {
String[] steps;
steps = simples.get(path);
if (steps == null) {
steps = Strings.toArray(Filesystem.SEPARATOR.split(path));
simples.put(path, steps);
}
return Dom.getChildElements(context, steps);
}
public List nodesNormal(Node context, String expression) {
int size;
NodeList nodes;
List result;
try {
nodes = (NodeList) compile(expression).evaluate(context, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new RuntimeException("invalid xpath: " + expression, e);
}
size = nodes.getLength();
result = new ArrayList(size);
for (int i = 0; i < size; i++) {
result.add(nodes.item(i));
}
return result;
}
//--
public static boolean isSimple(String path) {
int i;
int max;
char c;
max = path.length();
if (max == 0) {
return false;
}
if (path.charAt(0) == '/') {
return false;
}
for (i = 0; i < max; i++) {
c = path.charAt(i);
if (c == '/') {
if (i > 0 && path.charAt(i - 1) == '/') {
return false;
}
} else {
if (c != '_' && c != '-' && !Character.isLetter(c) && !Character.isDigit(c)) {
return false;
}
}
}
return true;
}
private XPathExpression compile(String path) {
XPathExpression cached;
XPath xpath;
cached = normals.get(path);
if (cached == null) {
xpath = factory.newXPath();
if (namespaceContext != null) {
xpath.setNamespaceContext(namespaceContext);
}
try {
cached = xpath.compile(path);
} catch (XPathExpressionException e) {
throw new RuntimeException("invalid xpath: " + path, e);
}
normals.put(path, cached);
}
return cached;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy