1 17 package org.apache.excalibur.xml.xpath; 18 19 20 import org.w3c.dom.*; 21 22 31 public final class XPathUtil { 32 33 57 public static Node getSingleNode(XPathProcessor processor, 58 Node rootNode, 59 String path) 60 throws XPathException { 61 if (path == null) { 64 throw new XPathException("XPath is required."); 65 } 66 if (rootNode == null) return rootNode; 67 68 if (path.length() == 0 || path.equals("/") == true) return rootNode; 69 70 Node testNode = searchSingleNode(processor, rootNode, path); 73 if (testNode != null) return testNode; 74 75 if (path.startsWith("/") == true) path = path.substring(1); if (path.endsWith("/") == true) { path = path.substring(0, path.length() - 1); 78 } 79 80 Node parent = rootNode; 82 int pos; 83 int posSelector; 84 do { 85 pos = path.indexOf("/"); posSelector = path.indexOf("["); 87 if (posSelector != -1 && posSelector < pos) { 88 posSelector = path.indexOf("]"); 89 pos = path.indexOf("/", posSelector); 90 } 91 92 String nodeName; 93 boolean isAttribute = false; 94 if (pos != -1) { nodeName = path.substring(0, pos); path = path.substring(pos+1); } else { 98 nodeName = path; 99 } 100 101 if (nodeName.startsWith("@") == true) { 103 isAttribute = true; 104 } 105 106 Node singleNode = searchSingleNode(processor, parent, nodeName); 107 108 if (singleNode == null) { 110 Node newNode; 111 int posSelect = nodeName.indexOf("["); 113 String XPathExp = null; 114 if (posSelect != -1) { 115 XPathExp = nodeName.substring(posSelect+1, nodeName.length()-1); 116 nodeName = nodeName.substring(0, posSelect); 117 } 118 if (isAttribute == true) { 119 try { 120 newNode = rootNode.getOwnerDocument().createAttributeNS(null, nodeName.substring(1)); 121 } catch (DOMException local) { 122 throw new XPathException("Unable to create new DOM node: '"+nodeName+"'.", local); 123 } 124 } else { 125 try { 126 newNode = rootNode.getOwnerDocument().createElementNS(null, nodeName); 127 } catch (DOMException local) { 128 throw new XPathException("Unable to create new DOM node: '"+nodeName+"'.", local); 129 } 130 if (XPathExp != null) { 131 java.util.List attrValuePairs = new java.util.ArrayList (4); 132 boolean noError = true; 133 134 String attr; 135 String value; 136 java.util.StringTokenizer tokenizer = new java.util.StringTokenizer (XPathExp, "= "); 138 while (tokenizer.hasMoreTokens() == true) { 139 attr = tokenizer.nextToken(); 140 if (attr.startsWith("@") == true) { 141 if (tokenizer.hasMoreTokens() == true) { 142 value = tokenizer.nextToken(); 143 if (value.startsWith("'") && value.endsWith("'")) value = value.substring(1, value.length()-1); 144 if (value.startsWith("\"") && value.endsWith("\"")) value = value.substring(1, value.length()-1); 145 attrValuePairs.add(attr.substring(1)); 146 attrValuePairs.add(value); 147 } else { 148 noError = false; 149 } 150 } else if (attr.trim().equals("and") == false) { 151 noError = false; 152 } 153 } 154 if (noError == true) { 155 for(int l=0;l<attrValuePairs.size();l=l+2) { 156 ((Element)newNode).setAttributeNS(null, (String )attrValuePairs.get(l), 157 (String )attrValuePairs.get(l+1)); 158 } 159 } 160 } 161 } 162 parent.appendChild(newNode); 163 parent = newNode; 164 } else { 165 parent = singleNode; 166 } 167 } while (pos != -1); 168 return parent; 169 } 170 171 181 public static Node searchSingleNode(XPathProcessor processor, 182 Node contextNode, 183 String str) { 184 String [] pathComponents = buildPathArray(str); 185 if (pathComponents == null) { 186 return processor.selectSingleNode(contextNode, str); 187 } else { 188 return getFirstNodeFromPath(contextNode, pathComponents, false); 189 } 190 } 191 192 201 public static NodeList searchNodeList(XPathProcessor processor, 202 Node contextNode, 203 String str) { 204 String [] pathComponents = buildPathArray(str); 205 if (pathComponents == null) { 206 return processor.selectNodeList(contextNode, str); 207 } else { 208 return getNodeListFromPath(contextNode, pathComponents); 209 } 210 } 211 212 217 public static String [] buildPathArray(String xpath) { 218 String [] result = null; 219 if (xpath != null && xpath.charAt(0) != '/') { 220 int components = 1; 222 int i, l; 223 l = xpath.length(); 224 boolean found = false; 225 i = 0; 226 while (i < l && found == false) { 227 switch (xpath.charAt(i)) { 228 case '[' : found = true; break; 229 case '(' : found = true; break; 230 case '*' : found = true; break; 231 case '@' : found = true; break; 232 case ':' : found = true; break; 233 case '/' : components++; 234 default: i++; 235 } 236 } 237 if (found == false) { 238 result = new String [components]; 239 if (components == 1) { 240 result[components-1] = xpath; 241 } else { 242 i = 0; 243 int start = 0; 244 components = 0; 245 while (i < l) { 246 if (xpath.charAt(i) == '/') { 247 result[components] = xpath.substring(start, i); 248 start = i+1; 249 components++; 250 } 251 i++; 252 } 253 result[components] = xpath.substring(start); 254 } 255 } 256 } 257 return result; 258 } 259 260 270 public static Node getFirstNodeFromPath(Node contextNode, 271 final String [] path, 272 final boolean create) { 273 if (contextNode == null || path == null || path.length == 0) 274 return contextNode; 275 Node item = getFirstNodeFromPath(contextNode, path, 0); 277 if (item == null && create == true) { 278 int i = 0; 279 NodeList childs; 280 boolean found; 281 int m, l; 282 while (contextNode != null && i < path.length) { 283 childs = contextNode.getChildNodes(); 284 found = false; 285 if (childs != null) { 286 m = 0; 287 l = childs.getLength(); 288 while (found == false && m < l) { 289 item = childs.item(m); 290 if (item.getNodeType() == Document.ELEMENT_NODE 291 && item.getLocalName().equals(path[i]) == true) { 292 found = true; 293 contextNode = item; 294 } 295 m++; 296 } 297 } 298 if (found == false) { 299 Element e = contextNode.getOwnerDocument().createElementNS(null, path[i]); 300 contextNode.appendChild(e); 301 contextNode = e; 302 } 303 i++; 304 } 305 item = contextNode; 306 } 307 return item; 308 } 309 310 313 private static Node getFirstNodeFromPath(final Node contextNode, 314 final String [] path, 315 final int startIndex) { 316 int i = 0; 317 NodeList childs; 318 boolean found; 319 int l; 320 Node item = null; 321 322 childs = contextNode.getChildNodes(); 323 found = false; 324 if (childs != null) { 325 i = 0; 326 l = childs.getLength(); 327 while (found == false && i < l) { 328 item = childs.item(i); 329 if (item.getNodeType() == Document.ELEMENT_NODE 330 && path[startIndex].equals(item.getLocalName()!=null?item.getLocalName():item.getNodeName())) { 331 if (startIndex == path.length-1) { 332 found = true; 333 } else { 334 item = getFirstNodeFromPath(item, path, startIndex+1); 335 if (item != null) found = true; 336 } 337 } 338 if (found == false) { 339 i++; 340 } 341 } 342 if (found == false) { 343 item = null; 344 } 345 } 346 return item; 347 } 348 349 357 public static NodeList getNodeListFromPath(Node contextNode, 358 String [] path) { 359 if (contextNode == null) return new NodeListImpl(); 360 if (path == null || path.length == 0) { 361 return new NodeListImpl(new Node[] {contextNode}); 362 } 363 NodeListImpl result = new NodeListImpl(); 364 try { 365 getNodesFromPath(result, contextNode, path, 0); 366 } catch (NullPointerException npe) { 367 throw new NullPointerException ("XMLUtil.getNodeListFromPath() did catch a NullPointerException."+ 370 "This might be due to a missconfigured XML parser which does not use DOM Level 2."+ 371 "Make sure that you use the XML parser shipped with Cocoon."); 372 } 373 return result; 374 } 375 376 379 private static void getNodesFromPath(final NodeListImpl result, 380 final Node contextNode, 381 final String [] path, 382 final int startIndex) { 383 final NodeList childs = contextNode.getChildNodes(); 384 int m, l; 385 Node item; 386 if (startIndex == (path.length-1)) { 387 if (childs != null) { 388 m = 0; 389 l = childs.getLength(); 390 while (m < l) { 391 item = childs.item(m); 392 if (item.getNodeType() == Document.ELEMENT_NODE) { 393 if (path[startIndex].equals(item.getLocalName()!=null?item.getLocalName():item.getNodeName()) == true) { 395 result.addNode(item); 396 } 397 } 398 m++; 399 } 400 } 401 } else { 402 if (childs != null) { 403 m = 0; 404 l = childs.getLength(); 405 while (m < l) { 406 item = childs.item(m); 407 if (item.getNodeType() == Document.ELEMENT_NODE) { 408 if (path[startIndex].equals(item.getLocalName()!=null?item.getLocalName():item.getNodeName()) == true) { 410 getNodesFromPath(result, item, path, startIndex+1); 411 } 412 } 413 m++; 414 } 415 } 416 } 417 } 418 419 428 public static String getValueOf(XPathProcessor processor, 429 Node root, String path) 430 throws XPathException { 431 if (path == null) { 432 throw new XPathException("Not a valid XPath: " + path); 433 } 434 if (root == null) return null; 435 if (path.startsWith("/") == true) path = path.substring(1); if (path.endsWith("/") == true) { path = path.substring(0, path.length() - 1); 438 } 439 440 Node node = searchSingleNode(processor, root, path); 441 if (node != null) { 442 return getValueOfNode(processor, node); 443 } 444 return null; 445 } 446 447 457 public static String getValueOf(XPathProcessor processor, 458 Node root, 459 String path, 460 String defaultValue) 461 throws XPathException { 462 String value = getValueOf(processor, root, path); 463 if (value == null) value = defaultValue; 464 465 return value; 466 } 467 468 479 public static boolean getValueAsBooleanOf(XPathProcessor processor, 480 Node root, 481 String path) 482 throws XPathException { 483 String value = getValueOf(processor, root, path); 484 if (value == null) { 485 throw new XPathException("No such node: " + path); 486 } 487 return Boolean.valueOf(value).booleanValue(); 488 } 489 490 502 public static boolean getValueAsBooleanOf(XPathProcessor processor, 503 Node root, 504 String path, 505 boolean defaultValue) 506 throws XPathException { 507 String value = getValueOf(processor, root, path); 508 if (value == null) { 509 return defaultValue; 510 } 511 return Boolean.valueOf(value).booleanValue(); 512 } 513 514 519 public static String getValueOfNode(XPathProcessor processor, 520 Node node) { 521 if (node == null) return null; 522 if (node.getNodeType() == Node.ATTRIBUTE_NODE) { 523 return node.getNodeValue(); 524 } else { 525 String value = null; 526 node.normalize(); 527 NodeList childs = node.getChildNodes(); 528 int i, l; 529 i = 0; 530 l = childs.getLength(); 531 while (i < l && value == null) { 532 if (childs.item(i).getNodeType() == Node.TEXT_NODE) 533 value = childs.item(i).getNodeValue().trim(); 534 else 535 i++; 536 } 537 return value; 538 } 539 } 540 541 547 public static String getValueOfNode(XPathProcessor processor, 548 Node node, String defaultValue) { 549 String value = getValueOfNode(processor, node); 550 if (value == null) value = defaultValue; 551 return value; 552 } 553 554 555 } 556 | Popular Tags |