/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.tomcat.util; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Few simple utils to read DOM * * @author Costin Manolache */ public class DomUtil { private static org.apache.juli.logging.Log log= org.apache.juli.logging.LogFactory.getLog( DomUtil.class ); // -------------------- DOM utils -------------------- /** Get the trimed text content of a node or null if there is no text */ public static String getContent(Node n ) { if( n==null ) return null; Node n1=DomUtil.getChild(n, Node.TEXT_NODE); if( n1==null ) return null; String s1=n1.getNodeValue(); return s1.trim(); } /** Get the first element child. * @param parent lookup direct childs * @param name name of the element. If null return the first element. */ public static Node getChild( Node parent, String name ) { if( parent==null ) return null; Node first=parent.getFirstChild(); if( first==null ) return null; for (Node node = first; node != null; node = node.getNextSibling()) { //System.out.println("getNode: " + name + " " + node.getNodeName()); if( node.getNodeType()!=Node.ELEMENT_NODE) continue; if( name != null && name.equals( node.getNodeName() ) ) { return node; } if( name == null ) { return node; } } return null; } public static String getAttribute(Node element, String attName ) { NamedNodeMap attrs=element.getAttributes(); if( attrs==null ) return null; Node attN=attrs.getNamedItem(attName); if( attN==null ) return null; return attN.getNodeValue(); } public static void setAttribute(Node node, String attName, String val) { NamedNodeMap attributes=node.getAttributes(); Node attNode=node.getOwnerDocument().createAttribute(attName); attNode.setNodeValue( val ); attributes.setNamedItem(attNode); } public static void removeAttribute( Node node, String attName ) { NamedNodeMap attributes=node.getAttributes(); attributes.removeNamedItem(attName); } /** Set or replace the text value */ public static void setText(Node node, String val) { Node chld=DomUtil.getChild(node, Node.TEXT_NODE); if( chld == null ) { Node textN=node.getOwnerDocument().createTextNode(val); node.appendChild(textN); return; } // change the value chld.setNodeValue(val); } /** Find the first direct child with a given attribute. * @param parent * @param elemName name of the element, or null for any * @param attName attribute we're looking for * @param attVal attribute value or null if we just want any */ public static Node findChildWithAtt(Node parent, String elemName, String attName, String attVal) { Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE); if( attVal== null ) { while( child!= null && ( elemName==null || elemName.equals( child.getNodeName())) && DomUtil.getAttribute(child, attName) != null ) { child=getNext(child, elemName, Node.ELEMENT_NODE ); } } else { while( child!= null && ( elemName==null || elemName.equals( child.getNodeName())) && ! attVal.equals( DomUtil.getAttribute(child, attName)) ) { child=getNext(child, elemName, Node.ELEMENT_NODE ); } } return child; } /** Get the first child's content ( ie it's included TEXT node ). */ public static String getChildContent( Node parent, String name ) { Node first=parent.getFirstChild(); if( first==null ) return null; for (Node node = first; node != null; node = node.getNextSibling()) { //System.out.println("getNode: " + name + " " + node.getNodeName()); if( name.equals( node.getNodeName() ) ) { return getContent( node ); } } return null; } /** 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; } /** Get the next sibling with the same name and type */ public static Node getNext( Node current ) { String name=current.getNodeName(); int type=current.getNodeType(); return getNext( current, name, type); } /** Return the next sibling with a given name and type */ public static Node getNext( Node current, String name, int type) { Node first=current.getNextSibling(); if( first==null ) return null; for (Node node = first; node != null; node = node.getNextSibling()) { if( type >= 0 && node.getNodeType() != type ) continue; //System.out.println("getNode: " + name + " " + node.getNodeName()); if( name==null ) return node; if( name.equals( node.getNodeName() ) ) { return node; } } return null; } public static class NullResolver implements EntityResolver { public InputSource resolveEntity (String publicId, String systemId) throws SAXException, IOException { if( log.isTraceEnabled()) log.trace("ResolveEntity: " + publicId + " " + systemId); return new InputSource(new StringReader("")); } } public static void setAttributes( Object o, Node parent) { NamedNodeMap attrs=parent.getAttributes(); if( attrs==null ) return; for (int i=0; i<attrs.getLength(); i++ ) { Node n=attrs.item(i); String name=n.getNodeName(); String value=n.getNodeValue(); if( log.isTraceEnabled() ) log.trace("Attribute " + parent.getNodeName() + " " + name + "=" + value); try { IntrospectionUtils.setProperty(o, name, value); } catch( Exception ex ) { ex.printStackTrace(); } } } /** Read XML as DOM. */ public static Document readXml(InputStream is) throws SAXException, IOException, ParserConfigurationException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setIgnoringComments(false); dbf.setIgnoringElementContentWhitespace(true); //dbf.setCoalescing(true); //dbf.setExpandEntityReferences(true); DocumentBuilder db = null; db = dbf.newDocumentBuilder(); db.setEntityResolver( new NullResolver() ); // db.setErrorHandler( new MyErrorHandler()); Document doc = db.parse(is); return doc; } public static void writeXml( Node n, OutputStream os ) throws TransformerException { TransformerFactory tf=TransformerFactory.newInstance(); //identity Transformer t=tf.newTransformer(); t.setOutputProperty(OutputKeys.INDENT, "yes"); t.transform(new DOMSource( n ), new StreamResult( os )); } }