001package net.sf.logdistiller.xml; 002 003/* 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017import java.util.Iterator; 018import java.util.NoSuchElementException; 019import org.w3c.dom.Element; 020import org.w3c.dom.Node; 021import org.w3c.dom.NodeList; 022 023/** 024 * Miscellaneous utilities for DOM. 025 */ 026public class DOMUtils 027{ 028 private DOMUtils() 029 { 030 } 031 032 public static String getPCDATAByTagName( Element elmt, String tagName ) 033 { 034 return getPCDATAByTagName( elmt, tagName, false ); 035 } 036 037 public static String getPCDATAByTagName( Element elmt, String tagName, boolean normalize ) 038 { 039 Iterator<Element> iter = getChildElementsByTagName( elmt, tagName ); 040 if ( !iter.hasNext() ) 041 { 042 return null; 043 } 044 return getPCDATA( (Element) iter.next(), normalize ); 045 } 046 047 /** 048 * Computes the resulting string of a <code>#PCDATA</code> element: it can consist in the XML document of a 049 * combination of nodes Text, EntityReference and CDATASection, with Comment. 050 * 051 * @param normalize normalize the element before computing? 052 */ 053 public static String getPCDATA( Element element, boolean normalize ) 054 { 055 if ( normalize ) 056 { 057 element.normalize(); 058 } 059 StringBuffer buff = new StringBuffer(); 060 NodeList list = element.getChildNodes(); 061 int len = list.getLength(); 062 for ( int i = 0; i < len; i++ ) 063 { 064 Node n = list.item( i ); 065 switch ( n.getNodeType() ) 066 { 067 case Node.TEXT_NODE: 068 case Node.CDATA_SECTION_NODE: 069 buff.append( n.getNodeValue() ); 070 break; 071 case Node.ENTITY_REFERENCE_NODE: 072 buff.append( n.getFirstChild().getNodeValue() ); 073 break; 074 case Node.COMMENT_NODE: 075 break; // ignore comments 076 default: // should not occur if really #PCDATA 077 throw new IllegalArgumentException( "element '" + element.getNodeName() 078 + "' is not #PCDATA because it " + "contains a " + getNodeTypeAsString( n ) + " node" ); 079 } 080 } 081 return buff.toString(); 082 } 083 084 public static String getPCDATA( Element elmt ) 085 { 086 return getPCDATA( elmt, false ); 087 } 088 089 public static Iterator<Element> getChildElementsByTagName( Element element, String tagName ) 090 { 091 return new ElementIterator( element.getChildNodes(), tagName ); 092 } 093 094 public static String getNodeTypeAsString( Node node ) 095 { 096 int type = node.getNodeType(); 097 switch ( type ) 098 { 099 case Node.ELEMENT_NODE: 100 return "Element"; 101 case Node.ATTRIBUTE_NODE: 102 return "Attribute"; 103 case Node.TEXT_NODE: 104 return "Text"; 105 case Node.CDATA_SECTION_NODE: 106 return "CDATASection"; 107 case Node.ENTITY_REFERENCE_NODE: 108 return "EntityReference"; 109 case Node.ENTITY_NODE: 110 return "Entity"; 111 case Node.PROCESSING_INSTRUCTION_NODE: 112 return "ProcessingInstruction"; 113 case Node.COMMENT_NODE: 114 return "Comment"; 115 case Node.DOCUMENT_NODE: 116 return "Document"; 117 case Node.DOCUMENT_TYPE_NODE: 118 return "DocumentType"; 119 case Node.DOCUMENT_FRAGMENT_NODE: 120 return "DocumentFragment"; 121 case Node.NOTATION_NODE: 122 return "Notation"; 123 default: 124 } 125 return "Unknown node type: " + type; 126 } 127 128 private static class ElementIterator 129 implements Iterator<Element> 130 { 131 private final NodeList nodeList; 132 133 private final String tagName; 134 135 private int index; 136 137 private Element next; 138 139 public ElementIterator( NodeList nodeList, String tagName ) 140 { 141 this.nodeList = nodeList; 142 this.tagName = tagName; 143 findNext(); 144 } 145 146 public boolean hasNext() 147 { 148 return ( next != null ); 149 } 150 151 private void findNext() 152 { 153 while ( index < nodeList.getLength() ) 154 { 155 Node node = nodeList.item( index ); 156 index++; 157 if ( ( node.getNodeType() == Node.ELEMENT_NODE ) 158 && ( ( tagName == null ) || node.getNodeName().equals( tagName ) ) ) 159 { 160 // next element found 161 next = (Element) node; 162 return; 163 } 164 } 165 // no element available any more 166 next = null; 167 } 168 169 public Element next() 170 { 171 if ( next == null ) 172 { 173 throw new NoSuchElementException(); 174 } 175 Element returnValue = next; 176 findNext(); 177 return returnValue; 178 } 179 180 public void remove() 181 { 182 throw new UnsupportedOperationException(); 183 } 184 } 185}