`
uule
  • 浏览: 6359419 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

XML工具类DOMUtil

 
阅读更多
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Vector;

import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * DOM utility
 * 
 * Thanks to Tom Fennelly from Jboss Group
 * 
 */
public class DOMUtil {
	
	/**
	 * Create a new W3C Document.
	 * <p/>
	 * Handles exceptions etc.
	 * @return The new Document instance.
	 * @throws ConfigurationException 
	 */
	public static Document createDocument() throws ConfigurationException {
		Document doc = null;
		
		try {
			doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
		} catch (ParserConfigurationException e) {
			throw new ConfigurationException("Failed to create ESB Configuration Document instance.");
		}
		
		return doc;
	}

    /**
     * Parse the supplied XML String and return the associated W3C Document object.
     *
     * @param xml XML String.
     * @return The W3C Document object associated with the input stream.
     */
    public static Document parse(String xml) throws SAXException, IOException {
        return parseStream(new ByteArrayInputStream(xml.getBytes()), false, false);
    }

    /**
     * Parse the XML stream and return the associated W3C Document object.
     * <p/>
     * Performs a namespace unaware parse.
     *
     * @param stream
     *            The stream to be parsed.
     * @param validate
     *            True if the document is to be validated, otherwise false.
     * @param expandEntityRefs
     *            Expand entity References as per
     *            {@link DocumentBuilderFactory#setExpandEntityReferences(boolean)}.
     * @return The W3C Document object associated with the input stream.
     */
    public static Document parseStream(InputStream stream, boolean validate,
            boolean expandEntityRefs) throws SAXException, IOException {
        return parseStream(stream, validate, expandEntityRefs, false);
    }

    /**
     * Parse the XML stream and return the associated W3C Document object.
     *
     * @param stream
     *            The stream to be parsed.
     * @param validate
     *            True if the document is to be validated, otherwise false.
     * @param expandEntityRefs
     *            Expand entity References as per
     *            {@link DocumentBuilderFactory#setExpandEntityReferences(boolean)}.
     * @param namespaceAware
     *            True if the document parse is to be namespace aware,
     *            otherwise false.
     * @return The W3C Document object associated with the input stream.
     */
    public static Document parseStream(InputStream stream, boolean validate,
            boolean expandEntityRefs, boolean namespaceAware) throws SAXException, IOException {
        if (stream == null) {
            throw new IllegalArgumentException(
                    "null 'stream' arg in method call.");
        }
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder docBuilder = null;

            factory.setValidating(validate);
            factory.setExpandEntityReferences(expandEntityRefs);
            factory.setNamespaceAware(namespaceAware);
            docBuilder = factory.newDocumentBuilder();

            return docBuilder.parse(stream);
        } catch (ParserConfigurationException e) {
            IllegalStateException state = new IllegalStateException(
                    "Unable to parse XML stream - XML Parser not configured correctly.");
            state.initCause(e);
            throw state;
        } catch (FactoryConfigurationError e) {
            IllegalStateException state = new IllegalStateException(
                    "Unable to parse XML stream - DocumentBuilderFactory not configured correctly.");
            state.initCause(e);
            throw state;
        }
    }

    public static String getAttribute(Element element, String name, String defaultVal) {
        if(element.hasAttribute(name)) {
            return element.getAttribute(name);
        } else {
            return defaultVal;
        }
    }

    /**
	 * Add an Element node to the supplied parent name.
	 * @param parent The parent to to which the new Element node is to be added.
	 * @param elementName The name of the Element to be added.
	 * @return The new Element.
	 */
	public static Element addElement(Node parent, String elementName) {
		Element element = null;
		
		if(parent instanceof Document) {
			element = ((Document)parent).createElement(elementName);
		} else {
			element = parent.getOwnerDocument().createElement(elementName);
		}
		parent.appendChild(element);
		
		return element;
	}
	
	/**
	 * Remove all attributes having an empty value.
	 * @param element The element to be processed.
	 */
	public static void removeEmptyAttributes(Element element) {
		NamedNodeMap attributes = element.getAttributes();
		int attribCount = attributes.getLength();
		
		for(int i = attribCount - 1; i >= 0; i--) {
			Attr attribute = (Attr) attributes.item(i);
			
			// Note - doesn't account for namespaces.  Not needed here !
			if(attribute.getValue().equals("")) {
				attributes.removeNamedItem(attribute.getName());
			}
		}
	}

	/**
	 * Serialize the supplied DOM node to the specified file in the specified output directory.
	 * @param node The DOM node to be serialised.
	 * @param outdir The directory into which the file is to be serialised.
	 * @param fileName The name of the file.
	 * @throws ConfigurationException Unable to serialise the node.
	 */
	public static void serialize(Node node, File outdir, String fileName) throws ConfigurationException {
		serialize(node, new StreamResult(new File(outdir, fileName)));
	}

    public static void serialize(Node node, OutputStream out) throws ConfigurationException {
      serialize(node, new StreamResult(out));
    }

    /**
      * Serialize the supplied DOM node to the supplied DOM StreamResult instance.
      * @param node The DOM node to be serialised.
      * @param streamRes The StreamResult into which the node is to be serialised.
      * @throws ConfigurationException Unable to serialise the node.
      */
    public static void serialize(Node node, StreamResult streamRes) throws ConfigurationException {
        serialize(node, streamRes, false);
    }

   /**
	 * Serialize the supplied DOM node to the supplied DOM StreamResult instance.
	 * @param node The DOM node to be serialised.
	 * @param streamRes The StreamResult into which the node is to be serialised.
     * @param omitXmlDecl Omit the XML declaration.
	 * @throws ConfigurationException Unable to serialise the node.
	 */
	public static void serialize(Node node, StreamResult streamRes, boolean omitXmlDecl) throws ConfigurationException {
		DOMSource domSource = new DOMSource(node);
		
		try {
			Transformer transformer = TransformerFactory.newInstance().newTransformer();

            // There's a bug in Java 5 re this code (formatting).
            // See http://forum.java.sun.com/thread.jspa?threadID=562510&start=0 and it explains the
            // whys of the following code.
            // transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "4");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, (omitXmlDecl?"yes":"no"));
			transformer.transform(domSource, streamRes);
		} catch (Exception e) {
			throw new ConfigurationException("Failed to serialize ESB Configuration Document instance.");
		}
	}

    /**
     * Count the DOM element nodes before the supplied node, having the specified
     * tag name, not including the node itself.
     * <p/>
     * Counts the sibling nodes.
     *
     * @param node    Node whose element siblings are to be counted.
     * @param tagName The tag name of the sibling elements to be counted.
     * @return The number of siblings elements before the supplied node with the
     *         specified tag name.
     */
    public static int countElementsBefore(Node node, String tagName) {
        Node parent = node.getParentNode();

        NodeList siblings = parent.getChildNodes();
        int count = 0;
        int siblingCount = siblings.getLength();

        for (int i = 0; i < siblingCount; i++) {
            Node sibling = siblings.item(i);

            if (sibling == node) {
                break;
            }
            if (sibling.getNodeType() == Node.ELEMENT_NODE && ((Element) sibling).getTagName().equals(tagName)) {
                count++;
            }
        }

        return count;
    }

    /**
     * Copy the nodes of a NodeList into the supplied list.
     * <p/>
     * This is not a cloneCollectionTemplateElement.  It's just a copy of the node references.
     * <p/>
     * Allows iteration over the Nodelist using the copy in the knowledge that
     * the list will remain the same length, even if we modify the underlying NodeList.
     * Using the NodeList can result in problems because elements can get removed from
     * the list while we're iterating over it.
     * <p/>
     * <i>This code was acquired donated by the Milyn Smooks project.</i>
     *
     * @param nodeList Nodelist to copy.
     * @return List copy.
     */
    public static List<Node> copyNodeList(NodeList nodeList) {
        List<Node> copy = new Vector<Node>();

        if (nodeList != null) {
            int nodeCount = nodeList.getLength();

            for (int i = 0; i < nodeCount; i++) {
                copy.add(nodeList.item(i));
            }
        }

        return copy;
    }
    
    public static Element getNextSiblingElement(Node node) {
        Node nextSibling = node.getNextSibling();

        while (nextSibling != null) {
            if (nextSibling.getNodeType() == Node.ELEMENT_NODE) {
                return (Element) nextSibling;
            }
            nextSibling = nextSibling.getNextSibling();
        }

        return null;
    }

    public static Node getFirstChildByType(Element element, int nodeType) {
        NodeList children = element.getChildNodes();
        int childCount = children.getLength();

        for(int i = 0; i < childCount; i++) {
            Node child = children.item(i);
            if (child.getNodeType() == nodeType) {
                return child;
            }
        }

        return null;
    }

    private static String ELEMENT_NAME_FUNC = "/name()";

    private static XPathFactory xPathFactory = XPathFactory.newInstance();

    /**
     * Get the W3C NodeList instance associated with the XPath selection
     * supplied.
     * <p/>
     * <b>NOTE</b>: Taken from Milyn Commons.
     *
     * @param node  The document node to be searched.
     * @param xpath The XPath String to be used in the selection.
     * @return The W3C NodeList instance at the specified location in the
     *         document, or null.
     */
    public static NodeList getNodeList(Node node, String xpath) {
        if (node == null) {
            throw new IllegalArgumentException(
                    "null 'document' arg in method call.");
        } else if (xpath == null) {
            throw new IllegalArgumentException(
                    "null 'xpath' arg in method call.");
        }
        try {
            XPath xpathEvaluater = xPathFactory.newXPath();

            if (xpath.endsWith(ELEMENT_NAME_FUNC)) {
                return (NodeList) xpathEvaluater.evaluate(xpath.substring(0,
                        xpath.length() - ELEMENT_NAME_FUNC.length()), node,
                        XPathConstants.NODESET);
            } else {
                return (NodeList) xpathEvaluater.evaluate(xpath, node,
                        XPathConstants.NODESET);
            }
        } catch (XPathExpressionException e) {
            throw new IllegalArgumentException("bad 'xpath' expression ["
                    + xpath + "].");
        }
    }

    /**
     * Get the W3C Node instance associated with the XPath selection supplied.
     * <p/>
     * <b>NOTE</b>: Taken from Milyn Commons.
     *
     * @param node  The document node to be searched.
     * @param xpath The XPath String to be used in the selection.
     * @return The W3C Node instance at the specified location in the document,
     *         or null.
     */
    public static Node getNode(Node node, String xpath) {
        NodeList nodeList = getNodeList(node, xpath);

        if (nodeList == null || nodeList.getLength() == 0) {
            return null;
        } else {
            return nodeList.item(0);
        }
    }

    /**
     * Get the name from the supplied element.
     * <p/>
     * Returns the {@link Node#getLocalName() localName} of the element
     * if set (namespaced element), otherwise the
     * element's {@link Element#getTagName() tagName} is returned.
     * <p/>
     * <b>NOTE</b>: Taken from Milyn Smooks.
     *
     * @param element The element.
     * @return The element name.
     */
    public static String getName(Element element) {

        String name = element.getLocalName();

        if(name != null) {
            return name;
        } else {
            return element.getTagName();
        }
    }
    /**
     * Copy child node references from source to target.
     * @param source Source Node.
     * @param target Target Node.
     */
    public static void copyChildNodes(Node source, Node target) {
        
        List nodeList = copyNodeList(source.getChildNodes());
        int childCount = nodeList.size();
        
        for(int i = 0; i < childCount; i++) {
            target.appendChild((Node)nodeList.get(i));
        }
    }

}

 

分享到:
评论

相关推荐

    JSUtils:JS工具类,适应大部分浏览器

    DOM工具类-DOMUtil 事件工具类-EventUtil 表格工具类-FormUtil XHR工具类-XHRUtil插件检测工具类-PluginDetectionUtil Cookie工具类(支持单层键)-CookieUtil Cookie工具类(支持双层键)-SubCookieUtil计算元素...

    电影院售票管理系统.doc

    - `util` 包通常存放工具类,这里的`DomUtil`是处理XML文档的工具类,提供了读取和保存XML文件的方法。 - `test` 包通常用于存放测试类,`Start`类可能是测试应用程序的主入口点。 - `service` 包则包含了业务...

    leaflet结合echarts4统计图.zip

    总结来说,"leaflet结合echarts4统计图"的实践意味着将地理空间信息与丰富的统计图形相结合,提供了一种强大的工具,用于揭示和解释基于位置的数据。这种技术在城市规划、环境研究、交通分析等领域有着广泛的应用。...

    Leaflet地图API中文版.pdf

    Util常用方法类提供了多种工具方法来辅助开发者使用Leaflet地图。 9. Leaflet地图API中文版的DOM常用方法类 Leaflet地图API中文版详细介绍了DOM常用方法类,包括DomEvent、DomUtil、PosAnimation等方面的知识点。...

    leaflet中文api

    - **LineUtil线处理和PolyUtil面处理**:用于处理线条和多边形的工具类。 #### DOM和事件处理 - **Class类**:定义了各种基本类如`Layer`、`InteractiveLayer`、`Control`和`Handler`。 - **Evented事件驱动**:...

    js常用DOM方法详解

    在前端开发中,DOM(Document Object Model)操作是不可或缺的一部分。JavaScript为开发者提供了丰富的方法来操作DOM,从而实现页面内容的动态更新和事件响应等。本文主要详细介绍了JavaScript中几个常用的DOM操作...

    37.(leaflet篇)leaflet叠加自定义tooltip展示.zip

    为了使自定义tooltip更美观,我们还需要在CSS中定义`custom-tooltip`类。例如,我们可以设置背景颜色、边框、字体样式等: ```css .custom-tooltip { position: absolute; background-color: #fff; border: 1px ...

    tui.code-snippet:一组便于开发 javascript 应用程序的实用方法

    artist_palette: 特征阿贾克斯发送 Ajax 请求大批处理数组浏览器检测浏览器收藏处理集合支持集合的 util 方法自定义事件添加/删除/触发自定义事件定义类定义类dom事件添加、删除、触发 DOM 事件控制鼠标事件domUtil ...

    tools-library:一组javascript工具。一套javascript工具库-专注于原生javascript兼容解决方案

    DOMUtil.js DOM操作兼容性解决方案 EventUtil.js浏览器事件兼容性解决方案 ECMAScript5.js让低版本浏览器支持ECMAScript的解决方案(整理自MDN Polyfill) Common.js建站通用方法 Tool.js常用工具方法 浏览器bug...

    Leaflet+GIS+API

    - `DomUtil`: DOM操作的实用工具。 - `PosAnimation`: 实现平滑动画效果。 - `Draggable`: 实现图层的拖动功能。 - `Class`: 基本的类系统。 - `Evented`: 事件驱动模型,用于监听和触发事件。 以上就是Leaflet中文...

    leaflet中文版

    - `Util`: 提供了多种实用工具方法。 - `Browser`: 提供有关浏览器的信息。 - `Transformation`: 提供坐标转换的方法。 - `LineUtil`: 提供处理线的方法。 - `PolyUtil`: 提供处理多边形的方法。 - **DOM常用...

    利用原生JS与jQuery实现数字线性变化的动画

    前言 大家应该都有所体会,在一些数据展示的专题页里,有时候希望数字能动态从某一个...var domUtil = { // 获取DOM元素 get: function(query) { var _this = this; if(document.querySelector) { return documen

    LeafletDataVisualizationFramework一个设计用于简化Leaflet地图库数据可视化与专题绘制的框架

    4. 创建图层:利用LDVF提供的图层类,如`GeoJSONLayer`或`HeatmapLayer`,并配置相应的样式和交互行为。 5. 添加图层到地图:将创建好的图层添加到地图实例中,显示在地图上。 6. 添加图例:根据图层类型,创建对应...

    70.(leaflet篇)leaflet流出迁徙图(canvas技术).zip

    Leaflet提供了一组丰富的地图操作工具,如缩放、平移、图层控制等。它支持多种在线地图服务,如OpenStreetMap、Google Maps和Bing Maps。要创建一个基本的Leaflet地图,我们需要在HTML文件中引入Leaflet库,并设置一...

Global site tag (gtag.js) - Google Analytics