001 package 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
017 import java.util.Iterator;
018 import java.util.NoSuchElementException;
019 import org.w3c.dom.Element;
020 import org.w3c.dom.Node;
021 import org.w3c.dom.NodeList;
022
023 /**
024 * Miscellaneous utilities for DOM.
025 */
026 public 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 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 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
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 )
140 {
141 this( nodeList, null );
142 }
143
144 public ElementIterator( NodeList nodeList, String tagName )
145 {
146 this.nodeList = nodeList;
147 this.tagName = tagName;
148 findNext();
149 }
150
151 public boolean hasNext()
152 {
153 return ( next != null );
154 }
155
156 private void findNext()
157 {
158 while ( index < nodeList.getLength() )
159 {
160 Node node = nodeList.item( index );
161 index++;
162 if ( ( node.getNodeType() == Node.ELEMENT_NODE )
163 && ( ( tagName == null ) || node.getNodeName().equals( tagName ) ) )
164 {
165 // next element found
166 next = (Element) node;
167 return;
168 }
169 }
170 // no element available any more
171 next = null;
172 }
173
174 public Object next()
175 {
176 if ( next == null )
177 {
178 throw new NoSuchElementException();
179 }
180 Object returnValue = next;
181 findNext();
182 return returnValue;
183 }
184
185 public void remove()
186 {
187 throw new UnsupportedOperationException();
188 }
189 }
190 }