1 /*
2 * @(#)XMLParsing.java 1.6 05/11/17
3 *
4 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * -Redistribution of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 *
12 * -Redistribution in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17 * be used to endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 *
32 * You acknowledge that this software is not designed, licensed or intended
33 * for use in the design, construction, operation or maintenance of any
34 * nuclear facility.
35 */
36
37 package jnlp.sample.servlet;
38
39 import org.w3c.dom.Attr;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.Text;
44
45 import java.util.ArrayList;
46 import java.util.List;
47
48 /**
49 * Contains handy methods for looking up information
50 * stored in XMLNodes.
51 */
52 public class XMLParsing
53 {
54
55 public static XMLNode convert( Node n )
56 {
57 if ( n == null )
58 {
59 return null;
60 }
61 else if ( n instanceof Text )
62 {
63 Text tn = (Text) n;
64 return new XMLNode( tn.getNodeValue() );
65 }
66 else if ( n instanceof Element )
67 {
68 Element en = (Element) n;
69
70 XMLAttribute xmlatts = null;
71 NamedNodeMap attributes = en.getAttributes();
72 for ( int i = attributes.getLength() - 1; i >= 0; i-- )
73 {
74 Attr ar = (Attr) attributes.item( i );
75 xmlatts = new XMLAttribute( ar.getName(), ar.getValue(), xmlatts );
76 }
77
78 // Convert childern
79 XMLNode thisNode = new XMLNode( en.getNodeName(), xmlatts, null, null );
80 ;
81 XMLNode last = null;
82 Node nn = en.getFirstChild();
83 while ( nn != null )
84 {
85 if ( thisNode.getNested() == null )
86 {
87 last = convert( nn );
88 thisNode.setNested( last );
89 }
90 else
91 {
92 XMLNode nnode = convert( nn );
93 last.setNext( nnode );
94 last = nnode;
95 }
96 last.setParent( thisNode );
97 nn = nn.getNextSibling();
98 }
99
100 return thisNode;
101 }
102 return null;
103 }
104
105 /**
106 * Returns true if the path exists in the document, otherwise false
107 */
108 static public boolean isElementPath( XMLNode root, String path )
109 {
110 return findElementPath( root, path ) != null;
111 }
112
113
114 /**
115 * Returns a string describing the current location in the DOM
116 */
117 static public String getPathString( XMLNode e )
118 {
119 return ( e == null || !( e.isElement() ) ) ? "" : getPathString( e.getParent() ) + "<" + e.getName() + ">";
120 }
121
122
123 /**
124 * Like getElementContents(...) but with a defaultValue of null
125 */
126 static public String getElementContent( XMLNode root, String path )
127 {
128 return getElementContent( root, path, null );
129 }
130
131 /**
132 * Like getElementContents(...) but with a defaultValue of null
133 */
134 static public String[] getMultiElementContent( XMLNode root, String path )
135 {
136 final List list = new ArrayList();
137 visitElements( root, path, new ElementVisitor()
138 {
139 public void visitElement( XMLNode n )
140 {
141 String value = getElementContent( n, "" );
142 if ( value != null )
143 {
144 list.add( value );
145 }
146 }
147 } );
148 if ( list.size() == 0 )
149 {
150 return null;
151 }
152 return (String[]) list.toArray( new String[list.size()] );
153 }
154
155 /**
156 * Returns the value of the last element tag in the path, e.g., <..><tag>value</tag>. The DOM is assumes
157 * to be normalized. If no value is found, the defaultvalue is returned
158 */
159 static public String getElementContent( XMLNode root, String path, String defaultvalue )
160 {
161 XMLNode e = findElementPath( root, path );
162 if ( e == null )
163 {
164 return defaultvalue;
165 }
166 XMLNode n = e.getNested();
167 if ( n != null && !n.isElement() )
168 {
169 return n.getName();
170 }
171 return defaultvalue;
172 }
173
174 /**
175 * Parses a path string of the form <tag1><tag2><tag3> and returns the specific Element
176 * node for that tag, or null if it does not exist. If multiple elements exists with same
177 * path the first is returned
178 */
179 static public XMLNode findElementPath( XMLNode elem, String path )
180 {
181 // End condition. Root null -> path does not exist
182 if ( elem == null )
183 {
184 return null;
185 }
186 // End condition. String empty, return current root
187 if ( path == null || path.length() == 0 )
188 {
189 return elem;
190 }
191
192 // Strip of first tag
193 int idx = path.indexOf( '>' );
194 String head = path.substring( 1, idx );
195 String tail = path.substring( idx + 1 );
196 return findElementPath( findChildElement( elem, head ), tail );
197 }
198
199 /**
200 * Returns an child element with the current tag name or null.
201 */
202 static public XMLNode findChildElement( XMLNode elem, String tag )
203 {
204 XMLNode n = elem.getNested();
205 while ( n != null )
206 {
207 if ( n.isElement() && n.getName().equals( tag ) )
208 {
209 return n;
210 }
211 n = n.getNext();
212 }
213 return null;
214 }
215
216 /**
217 * Iterator class
218 */
219 public abstract static class ElementVisitor
220 {
221 abstract public void visitElement( XMLNode e );
222 }
223
224 /**
225 * Visits all elements which matches the <path>. The iteration is only
226 * done on the last elment in the path.
227 */
228 static public void visitElements( XMLNode root, String path, ElementVisitor ev )
229 {
230 // Get last element in path
231 int idx = path.lastIndexOf( '<' );
232 String head = path.substring( 0, idx );
233 String tag = path.substring( idx + 1, path.length() - 1 );
234
235 XMLNode elem = findElementPath( root, head );
236 if ( elem == null )
237 {
238 return;
239 }
240
241 // Iterate through all child nodes
242 XMLNode n = elem.getNested();
243 while ( n != null )
244 {
245 if ( n.isElement() && n.getName().equals( tag ) )
246 {
247 ev.visitElement( n );
248 }
249 n = n.getNext();
250 }
251 }
252
253 static public void visitChildrenElements( XMLNode elem, ElementVisitor ev )
254 {
255 // Iterate through all child nodes
256 XMLNode n = elem.getNested();
257 while ( n != null )
258 {
259 if ( n.isElement() )
260 {
261 ev.visitElement( n );
262 }
263 n = n.getNext();
264 }
265 }
266 }
267