package com.googlecode.totallylazy.xml; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.functions.Curried2; import com.googlecode.totallylazy.Option; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.Strings; import com.googlecode.totallylazy.regex.Regex; import com.googlecode.totallylazy.time.Dates; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import java.util.List; import static com.googlecode.totallylazy.predicates.Predicates.not; import static com.googlecode.totallylazy.predicates.Predicates.nullValue; import static com.googlecode.totallylazy.Sequences.sequence; public class XPathFunctions { @XPathFunction("trim-and-join") public static String trimAndJoin(NodeList nodes, String delimiter) { return Xml.textContents(nodes).map(Strings.trim()).toString(unescape(delimiter)); } @XPathFunction("string-join") public static String stringJoin(NodeList nodes, String delimiter) { return Xml.textContents(nodes).toString(unescape(delimiter)); } @XPathFunction("if") public static Object IF(NodeList nodeList, Object matched, Object notMatched) { return nodeList.getLength() > 0 ? matched : notMatched; } @XPathFunction("or") public static Object or(List<Object> arguments) { return sequence(arguments).find(not(nullValue()).and(other -> !(other instanceof NodeList) || ((NodeList) other).getLength() != 0)).getOrNull(); } @XPathFunction("tokenize") public static NodeArrayList<Text> tokenize(NodeList input, String pattern) { return new NodeArrayList<Text>(Xml.sequence(input).flatMap(split(pattern))); } @XPathFunction("replace") public static NodeArrayList<Text> tokenize(NodeList input, String pattern, String replace) { return new NodeArrayList<Text>(Xml.sequence(input).map(replace(pattern, replace))); } @XPathFunction("time-in-millis") public static Long timeInMillis(NodeList dates) { Option<String> date = Xml.textContents(dates).headOption(); return date.map(s -> Dates.parse(s).getTime()).getOrNull(); } @XPathFunction("date-in-millis") public static Long dateInMillis(NodeList dates) { Option<String> date = Xml.textContents(dates).headOption(); return date.map(s -> Dates.stripTime(Dates.parse(s)).getTime()).getOrNull(); } private static Function1<Node, Sequence<Text>> split(final String pattern) { return node -> Regex.regex(pattern).split(node.getTextContent()).map(createText.apply(node)); } private static Function1<Node, Text> replace(final String pattern, final String replace) { return node -> createText(node, node.getTextContent().replaceAll(pattern, replace)); } public static Curried2<Node, String, Text> createText = XPathFunctions::createText; public static Text createText(Node nodeInDocument, String text) {return nodeInDocument.getOwnerDocument().createTextNode(text);} private static String unescape(String value) { return value.replace("\\n", "\n"); } }