All Downloads are FREE. Search and download functionalities are using the official Maven repository.

chaschev.util.DomUtils Maven / Gradle / Ivy

There is a newer version: 1.4
Show newest version
package chaschev.util;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;

import static org.w3c.dom.Node.ELEMENT_NODE;

/**
 * User: achaschev
 * Date: 4/5/13
 * Time: 3:46 PM
 */
public class DomUtils {
    public static final Predicate TRUE = new Predicate() {
        public boolean apply(Node node) {
            return true;
        }
    };

    public interface Predicate {

        /**
         * Applies this Predicate to the given object.
         *
         * @return the value of this Predicate when applied to input {@code t}
         */
        boolean apply(T t);
    }

    public static Element child(Element element, String tag) {
        final NodeList list = element.getChildNodes();

        for (int i = 0; i < list.getLength(); i++) {
            final Node item = list.item(i);

            if (item.getNodeType() == ELEMENT_NODE && hasLocalName(item, tag)) {

                return (Element) item;
            }
        }

        return null;
    }

    public static boolean hasLocalName(Node item, String tag) {
        final String nodeName = item.getNodeName();
        if (nodeName.endsWith(tag)) {
            int i = nodeName.length() - tag.length();
            return i == 0 || nodeName.charAt(i - 1) == ':';
        }

        return false;
    }

    public static Element childPath(Element element, String path) {
        final String[] elements = path.split("/");

        for (String s : elements) {
            element = child(element, s);
            if (element == null) return null;
        }

        return element;
    }

    public static Iterable children(final Element element, final String tag) {
        return children(element, new Predicate() {
            @Override
            public boolean apply(Node node) {
                return hasLocalName(node, tag);
            }
        });
    }

    public static Iterable children(final Element element) {
        return children(element, TRUE);
    }

    public static Iterable children(final Element element, final Predicate predicate) {
        return new Iterable() {
            @Override
            public Iterator iterator() {
                return new Iterator() {
                    final NodeList list = element.getChildNodes();

                    int i = 0;

                    @Override
                    public boolean hasNext() {
                        for (; i < list.getLength(); i++) {
                            final Node node = list.item(i);

                            if (node.getNodeType() == ELEMENT_NODE && predicate.apply(node)) {
                                break;
                            }
                        }
                        return i < list.getLength();
                    }

                    @Override
                    public Element next() {
                        return (Element) list.item(i++);
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException("todo .remove");
                    }
                };
            }
        };
    }

    /**
     * First tries to get the attribute value by doing an getAttributeNS on the element, if that gets an empty element it does a getAttribute without namespace.
     */
    public static String getAttribute(Element element, String attribute) {
        return element.getAttribute(attribute);
    }

    /**
     * Gets all descendant elements of the given parentElement with the given namespace and tagname and returns their text child as a list of String.
     */
    public static List childrenText(Element parentElement, String tagname) {
        final Iterable children = children(parentElement, tagname);

        List result = new ArrayList();

        for (Element element : children) {
            result.add(elementText(element));
        }

        return result;
    }

    /**
     * The contents of all Text nodes that are children of the given parentElement.
     * The result is trim()-ed.
     * 

* The reason for this more complicated procedure instead of just returning the data of the firstChild is that * when the text is Chinese characters then on Android each Characater is represented in the DOM as * an individual Text node. * * @param parentElement * @return */ public static String elementText(Element parentElement) { if (parentElement == null) { return null; } StringBuilder result = new StringBuilder(); NodeList childNodes = parentElement.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if ((node == null) || (node.getNodeType() != Node.TEXT_NODE)) { continue; } result.append(((Text) node).getData()); } return result.toString().trim(); } public static String elementToString(Node n) { return elementToString(n, 0, 4); } public static String elementToString(Node node, int depth, int maxDepth) { return elementToString(node, new HashSet(), depth, maxDepth); } private static String elementToString(Node n, Set visitedSet, int depth, int maxDepth) { if (depth >= maxDepth) { return "depth limit\n"; } if (visitedSet.contains(n)) { return "cycle to " + n.getLocalName() + "\n"; } else { visitedSet.add(n); } String name = n.getNodeName(); short type = n.getNodeType(); if (Node.CDATA_SECTION_NODE == type) { return "'); } else { sb.append("/>").append('\n'); } } else { sb.append('>').append('\n'); boolean hasValidChildren = false; for (int i = 0; i < children.getLength(); i++) { String childToString = elementToString(children.item(i), visitedSet, depth + 1, maxDepth); if (!"".equals(childToString)) { sb.append(childToString); hasValidChildren = true; } } if (!hasValidChildren && ((textContent = getTextContent(n)) != null)) { sb.append(textContent); } sb.append("'); } return sb.toString(); } public static String getTextContent(Node n) { if (n == null) return null; Node n1 = getChild(n, Node.TEXT_NODE); if (n1 == null) return null; String s1 = n1.getNodeValue(); return s1.trim(); } /** * Get the first direct child with a given type */ public static Node getChild(Node parent, int type) { Node n = parent.getFirstChild(); while (n != null && type != n.getNodeType()) { n = n.getNextSibling(); } if (n == null) return null; return n; } public static Document parseXml(String s){ try { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); dbFactory.setIgnoringElementContentWhitespace(true); dbFactory.setNamespaceAware(false); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(new ByteArrayInputStream(s.getBytes())); return doc; } catch (Exception e) { throw Exceptions.runtime(e); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy