001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.modeler.util; 018 019 import java.io.IOException; 020 import java.io.InputStream; 021 import java.io.OutputStream; 022 import java.io.StringReader; 023 024 import javax.xml.parsers.DocumentBuilder; 025 import javax.xml.parsers.DocumentBuilderFactory; 026 import javax.xml.parsers.ParserConfigurationException; 027 import javax.xml.transform.OutputKeys; 028 import javax.xml.transform.Transformer; 029 import javax.xml.transform.TransformerException; 030 import javax.xml.transform.TransformerFactory; 031 import javax.xml.transform.dom.DOMSource; 032 import javax.xml.transform.stream.StreamResult; 033 034 import org.w3c.dom.Document; 035 import org.w3c.dom.NamedNodeMap; 036 import org.w3c.dom.Node; 037 import org.xml.sax.EntityResolver; 038 import org.xml.sax.InputSource; 039 import org.xml.sax.SAXException; 040 041 042 /** 043 * Few simple utils to read DOM 044 * 045 * @author Costin Manolache 046 */ 047 public class DomUtil { 048 private static org.apache.commons.logging.Log log= 049 org.apache.commons.logging.LogFactory.getLog( DomUtil.class ); 050 051 // -------------------- DOM utils -------------------- 052 053 /** Get the trimed text content of a node or null if there is no text 054 */ 055 public static String getContent(Node n ) { 056 if( n==null ) return null; 057 Node n1=DomUtil.getChild(n, Node.TEXT_NODE); 058 059 if( n1==null ) return null; 060 061 String s1=n1.getNodeValue(); 062 return s1.trim(); 063 } 064 065 /** Get the first element child. 066 * @param parent lookup direct childs 067 * @param name name of the element. If null return the first element. 068 */ 069 public static Node getChild( Node parent, String name ) { 070 if( parent==null ) return null; 071 Node first=parent.getFirstChild(); 072 if( first==null ) return null; 073 074 for (Node node = first; node != null; 075 node = node.getNextSibling()) { 076 //System.out.println("getNode: " + name + " " + node.getNodeName()); 077 if( node.getNodeType()!=Node.ELEMENT_NODE) 078 continue; 079 if( name != null && 080 name.equals( node.getNodeName() ) ) { 081 return node; 082 } 083 if( name == null ) { 084 return node; 085 } 086 } 087 return null; 088 } 089 090 public static String getAttribute(Node element, String attName ) { 091 NamedNodeMap attrs=element.getAttributes(); 092 if( attrs==null ) return null; 093 Node attN=attrs.getNamedItem(attName); 094 if( attN==null ) return null; 095 return attN.getNodeValue(); 096 } 097 098 public static void setAttribute(Node node, String attName, String val) { 099 NamedNodeMap attributes=node.getAttributes(); 100 Node attNode=node.getOwnerDocument().createAttribute(attName); 101 attNode.setNodeValue( val ); 102 attributes.setNamedItem(attNode); 103 } 104 105 public static void removeAttribute( Node node, String attName ) { 106 NamedNodeMap attributes=node.getAttributes(); 107 attributes.removeNamedItem(attName); 108 } 109 110 111 /** Set or replace the text value 112 */ 113 public static void setText(Node node, String val) { 114 Node chld=DomUtil.getChild(node, Node.TEXT_NODE); 115 if( chld == null ) { 116 Node textN=node.getOwnerDocument().createTextNode(val); 117 node.appendChild(textN); 118 return; 119 } 120 // change the value 121 chld.setNodeValue(val); 122 } 123 124 /** Find the first direct child with a given attribute. 125 * @param parent 126 * @param elemName name of the element, or null for any 127 * @param attName attribute we're looking for 128 * @param attVal attribute value or null if we just want any 129 */ 130 public static Node findChildWithAtt(Node parent, String elemName, 131 String attName, String attVal) { 132 133 Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE); 134 if( attVal== null ) { 135 while( child!= null && 136 ( elemName==null || elemName.equals( child.getNodeName())) && 137 DomUtil.getAttribute(child, attName) != null ) { 138 child=getNext(child, elemName, Node.ELEMENT_NODE ); 139 } 140 } else { 141 while( child!= null && 142 ( elemName==null || elemName.equals( child.getNodeName())) && 143 ! attVal.equals( DomUtil.getAttribute(child, attName)) ) { 144 child=getNext(child, elemName, Node.ELEMENT_NODE ); 145 } 146 } 147 return child; 148 } 149 150 151 /** Get the first child's content ( ie it's included TEXT node ). 152 */ 153 public static String getChildContent( Node parent, String name ) { 154 Node first=parent.getFirstChild(); 155 if( first==null ) return null; 156 for (Node node = first; node != null; 157 node = node.getNextSibling()) { 158 //System.out.println("getNode: " + name + " " + node.getNodeName()); 159 if( name.equals( node.getNodeName() ) ) { 160 return getContent( node ); 161 } 162 } 163 return null; 164 } 165 166 /** Get the first direct child with a given type 167 */ 168 public static Node getChild( Node parent, int type ) { 169 Node n=parent.getFirstChild(); 170 while( n!=null && type != n.getNodeType() ) { 171 n=n.getNextSibling(); 172 } 173 if( n==null ) return null; 174 return n; 175 } 176 177 /** Get the next sibling with the same name and type 178 */ 179 public static Node getNext( Node current ) { 180 String name=current.getNodeName(); 181 int type=current.getNodeType(); 182 return getNext( current, name, type); 183 } 184 185 /** Return the next sibling with a given name and type 186 */ 187 public static Node getNext( Node current, String name, int type) { 188 Node first=current.getNextSibling(); 189 if( first==null ) return null; 190 191 for (Node node = first; node != null; 192 node = node.getNextSibling()) { 193 194 if( type >= 0 && node.getNodeType() != type ) continue; 195 //System.out.println("getNode: " + name + " " + node.getNodeName()); 196 if( name==null ) 197 return node; 198 if( name.equals( node.getNodeName() ) ) { 199 return node; 200 } 201 } 202 return null; 203 } 204 205 public static class NullResolver implements EntityResolver { 206 public InputSource resolveEntity (String publicId, 207 String systemId) 208 throws SAXException, IOException 209 { 210 if( log.isTraceEnabled()) 211 log.trace("ResolveEntity: " + publicId + " " + systemId); 212 return new InputSource(new StringReader("")); 213 } 214 } 215 216 public static void setAttributes( Object o, Node parent) 217 { 218 NamedNodeMap attrs=parent.getAttributes(); 219 if( attrs==null ) return; 220 221 for (int i=0; i<attrs.getLength(); i++ ) { 222 Node n=attrs.item(i); 223 String name=n.getNodeName(); 224 String value=n.getNodeValue(); 225 226 if( log.isTraceEnabled() ) 227 log.trace("Attribute " + parent.getNodeName() + " " + 228 name + "=" + value); 229 try { 230 IntrospectionUtils.setProperty(o, name, value); 231 } catch( Exception ex ) { 232 ex.printStackTrace(); 233 } 234 } 235 } 236 237 /** Read XML as DOM. 238 */ 239 public static Document readXml(InputStream is) 240 throws SAXException, IOException, ParserConfigurationException 241 { 242 DocumentBuilderFactory dbf = 243 DocumentBuilderFactory.newInstance(); 244 245 dbf.setValidating(false); 246 dbf.setIgnoringComments(false); 247 dbf.setIgnoringElementContentWhitespace(true); 248 //dbf.setCoalescing(true); 249 //dbf.setExpandEntityReferences(true); 250 251 DocumentBuilder db = null; 252 db = dbf.newDocumentBuilder(); 253 db.setEntityResolver( new NullResolver() ); 254 255 // db.setErrorHandler( new MyErrorHandler()); 256 257 Document doc = db.parse(is); 258 return doc; 259 } 260 261 public static void writeXml( Node n, OutputStream os ) 262 throws TransformerException 263 { 264 TransformerFactory tf=TransformerFactory.newInstance(); 265 //identity 266 Transformer t=tf.newTransformer(); 267 t.setOutputProperty(OutputKeys.INDENT, "yes"); 268 t.transform(new DOMSource( n ), new StreamResult( os )); 269 } 270 }