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

org.beanio.parser.xml.XmlNodeUtil Maven / Gradle / Ivy

/*
 * Copyright 2011 Kevin Seim
 * 
 * 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 org.beanio.parser.xml;

import javax.xml.XMLConstants;

import org.w3c.dom.*;

/**
 * Utility class for working with a document object model and XmlDefinition's. 
 * @author Kevin Seim
 * @since 1.1
 */
public class XmlNodeUtil {

    private XmlNodeUtil() { }
    
    /**
     * Unwraps an XML element when a wrapper is configured for the given XML definition.
     * Otherwise, just returns parent.
     * @param parent the parent XML element to unwrap
     * @param definition the definition of the XML node 
     * @return the wrapper child element if found, or null if not, or the parent
     *   if the XML node is not wrapped
     */
    public static Element unwrap(Element parent, XmlDefinition definition) {
        XmlDefinition wrapper = definition.getWrapper();
        if (wrapper != null) {
            Node node = findChild(parent, wrapper, 0);
            if (node == null || node.getNodeType() != Node.ELEMENT_NODE) {
                return null;
            }
            return (Element) node;
        }
        return parent;
    }
    
    /**
     * Tests if an element is nil.
     * @param element the element to test
     * @return true if the element is nil
     */
    public static boolean isNil(Element element) {
        String nil = element.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil");
        return "true".equals(nil) || "1".equals(nil);
    }
    
    /**
     * Returns the value of an attribute for an element.
     * @param element the element to check
     * @param definition the definition of the attribute to retrieve from the element
     * @return the defined attribute value, or null if the attribute was not
     *   found on the element
     */
    public static String getAttribute(Element element, XmlDefinition definition) {
        element = unwrap(element, definition);
        if (element == null) {
            return null;
        }
        
        if (definition.isNamespaceAware()) {
            if (element.hasAttributeNS(definition.getNamespace(), definition.getName())) {
                return element.getAttributeNS(definition.getNamespace(), definition.getName());
            }
        }
        else {
            if (element.hasAttribute(definition.getName())) {
                return element.getAttribute(definition.getName());
            }
        }
        return null;
    }
    
    /**
     * Returns the child text from a DOM node after adjusting for any node wrapping.
     * @param node the node to parse
     * @param definition the definition of the text node
     * @return the node text, or null if the node did not contain any text
     */
    public static String getText(Node node, XmlDefinition definition) {
        if (node.getNodeType() != Node.ELEMENT_NODE) {
            return null;
        }
        Node parent = unwrap((Element)node, definition);
        if (parent == null) {
            return null;
        }
        return getText(parent);
    }
    
    /**
     * Returns the child text from a DOM node.
     * @param node the node to parse
     * @return the node text, or null if the node did not contain any text
     */
    public static String getText(Node node) {
        StringBuilder s = null;
        Node child = node.getFirstChild();
        while (child != null) {    
            if (child.getNodeType() == Node.TEXT_NODE) {
                if (s == null) {
                    s = new StringBuilder();
                }
                s.append(((Text)child).getTextContent());
            }
            child = child.getNextSibling();
        }
        return s == null ? null : s.toString();
    }
    
    /**
     * Returns a sibling element that matches a given definition, or null if
     * no match is found.
     * @param sibling the sibling DOM element to begin the search
     * @param definition the node to search for
     * @return the matching element, or null if not found
     */
    public static Element findSibling(Element sibling, XmlDefinition definition) {
        String xmlName = definition.getName();
        String xmlNamespace = definition.getNamespace();
        
        Node node = sibling;
        if (node == null) {
            return null;
        }
        
        while ((node = node.getNextSibling()) != null) {
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            Element element = (Element) node;
            if (!element.getLocalName().equals(xmlName)) {
                continue;
            }
            if (definition.isNamespaceAware()) {
                String ns = element.getNamespaceURI();
                if (ns == null) {
                    if (xmlNamespace != null) {
                        continue;
                    }
                }
                else {
                    if (!ns.equals(xmlNamespace)) {
                        continue;
                    }
                }
            }
            return element;
        }
        return null;
    }
 
    /**
     * Finds the Nth matching child of a DOM element.
     * @param parent the parent DOM node
     * @param definition the node definition to search for
     * @param offset the occurrence of the matching node
     * @return the matching element, or null if no match is found
     */
    public static Element findChild(Node parent, XmlDefinition definition, int offset) {
        
        Node node = parent;
        if (definition.getWrapper() != null) {
            node = findChild(parent, definition.getWrapper(), 0);
        }
        if (node != null) {
            node = node.getFirstChild();
        }
        if (node == null) {
            return null;
        }
        
        String xmlName = definition.getName();
        String xmlNamespace = definition.getNamespace();
        
        int count = 0;
        do {
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            Element element = (Element) node;
            if (!element.getLocalName().equals(xmlName)) {
                continue;
            }
            if (definition.isNamespaceAware()) {
                String ns = element.getNamespaceURI();
                if (ns == null) {
                    if (xmlNamespace != null && xmlNamespace.length() != 0) {
                        continue;
                    }
                }
                else {
                    if (!ns.equals(xmlNamespace)) {
                        continue;
                    }
                }
            }
            if (count == offset) {
                return element;
            }
            ++count;
            
        } while ((node = node.getNextSibling()) != null);
        
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy