Implementation independent version of the XML Node.isEqualNode() method. - Java XML

Java examples for XML:XML Node

Description

Implementation independent version of the XML Node.isEqualNode() method.

Demo Code

/**/*from  w  w  w  .  j  a  v a2  s .co m*/
 *  Copyright 2012 Sven Ewald
 *
 *  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 com.java2s;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import java.util.List;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Main {
    /**
     *
     */
    private static final Comparator<? super Node> ATTRIBUTE_NODE_COMPARATOR = new Comparator<Node>() {
        private int compareMaybeNull(final Comparable<Object> a,
                final Object b) {
            if (a == b) {
                return 0;
            }
            if (a == null) {
                return -1;
            }
            if (b == null) {
                return 1;
            }
            return a.compareTo(b);
        }

        @Override
        public int compare(final Node o1, final Node o2) {
            Comparable<Object>[] c1 = getNodeAttributes(o1);
            Comparable<Object>[] c2 = getNodeAttributes(o2);
            assert c1.length == c2.length;
            for (int i = 0; i < c1.length; ++i) {
                int result = compareMaybeNull(c1[i], c2[i]);
                if (result != 0) {
                    return result;
                }
            }
            return 0;
        }
    };

    /**
     * Implementation independent version of the Node.isEqualNode() method. Matches the same
     * algorithm as the nodeHashCode method. <br>
     * Two nodes are equal if and only if the following conditions are satisfied:
     * <ul>
     * <li>The two nodes are of the same type.</li>
     * <li>The following string attributes are equal: <code>nodeName</code>, <code>localName</code>,
     * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code> . This is: they are
     * both <code>null</code>, or they have the same length and are character for character
     * identical.</li>
     * <li>The <code>attributes</code> <code>NamedNodeMaps</code> are equal. This is: they are both
     * <code>null</code>, or they have the same length and for each node that exists in one map
     * there is a node that exists in the other map and is equal, although not necessarily at the
     * same index.</li>
     * <li>The <code>childNodes</code> <code>NodeLists</code> are equal. This is: they are both
     * <code>null</code>, or they have the same length and contain equal nodes at the same index.
     * Note that normalization can affect equality; to avoid this, nodes should be normalized before
     * being compared.</li>
     * </ul>
     * <br>
     * For two <code>DocumentType</code> nodes to be equal, the following conditions must also be
     * satisfied:
     * <ul>
     * <li>The following string attributes are equal: <code>publicId</code>, <code>systemId</code>,
     * <code>internalSubset</code>.</li>
     * <li>The <code>entities</code> <code>NamedNodeMaps</code> are equal.</li>
     * <li>The <code>notations</code> <code>NamedNodeMaps</code> are equal.</li>
     * </ul>
     *
     * @param a
     * @param b
     * @return true if and only if the nodes are equal in the manner explained above
     */
    public static boolean nodesAreEqual(final Node a, final Node b) {
        if (a == b) {
            return true;
        }
        if ((a == null) || (b == null)) {
            return false;
        }
        if (!Arrays.equals(getNodeAttributes(a), getNodeAttributes(b))) {
            return false;
        }
        if (!namedNodeMapsAreEqual(a.getAttributes(), b.getAttributes())) {
            return false;
        }
        if (!nodeListsAreEqual(a.getChildNodes(), b.getChildNodes())) {
            return false;
        }
        return true;
    }

    @SuppressWarnings("unchecked")
    private static Comparable<Object>[] getNodeAttributes(final Node node) {
        return new Comparable[] { Short.valueOf(node.getNodeType()),
                node.getNodeName(), node.getLocalName(),
                node.getNamespaceURI(), node.getPrefix(),
                node.getNodeValue() };
    }

    /**
     * NamedNodeMaps (e.g. the attributes of a node) are equal if for each containing node an equal
     * node exists in the other map.
     *
     * @param a
     * @param b
     * @return
     */
    private static boolean namedNodeMapsAreEqual(final NamedNodeMap a,
            final NamedNodeMap b) {
        if (a == b) {
            return true;
        }
        if ((a == null) || (b == null)) {
            return false;
        }
        if (a.getLength() != b.getLength()) {
            return false;
        }

        List<Node> listA = new ArrayList<Node>(a.getLength());
        List<Node> listB = new ArrayList<Node>(a.getLength());

        for (int i = 0; i < a.getLength(); ++i) {
            listA.add(a.item(i));
            listB.add(b.item(i));
        }

        Collections.sort(listA, ATTRIBUTE_NODE_COMPARATOR);
        Collections.sort(listB, ATTRIBUTE_NODE_COMPARATOR);
        for (Node n1 : listA) {
            if (!nodesAreEqual(n1, listB.remove(0))) {
                return false;
            }
        }
        return true;
    }

    /**
     * NodeLists are equal if and only if their size is equal and the containing nodes at the same
     * indexes are equal.
     *
     * @param a
     * @param b
     * @return
     */
    private static boolean nodeListsAreEqual(final NodeList a,
            final NodeList b) {
        if (a == b) {
            return true;
        }
        if ((a == null) || (b == null)) {
            return false;
        }
        if (a.getLength() != b.getLength()) {
            return false;
        }
        for (int i = 0; i < a.getLength(); ++i) {
            if (!nodesAreEqual(a.item(i), b.item(i))) {
                return false;
            }
        }
        return true;
    }
}

Related Tutorials