1 28 29 package com.caucho.xpath.expr; 30 31 import com.caucho.util.CharBuffer; 32 import com.caucho.xml.XmlChar; 33 import com.caucho.xpath.Expr; 34 import com.caucho.xpath.ExprEnvironment; 35 import com.caucho.xpath.XPathException; 36 37 import org.w3c.dom.Node ; 38 39 import java.util.ArrayList ; 40 import java.util.Iterator ; 41 42 45 public class StringExpr extends Expr { 46 private int _code; 48 private Expr _left; 50 private Expr _right; 52 private Expr _third; 54 private String _value; 55 private ArrayList _args; 57 58 66 public StringExpr(int code, Expr left, Expr right, Expr third) 67 { 68 _code = code; 69 _left = left; 70 _right = right; 71 _third = third; 72 } 73 74 public StringExpr(int code, Expr left, Expr right) 75 { 76 _code = code; 77 _left = left; 78 _right = right; 79 } 80 81 public StringExpr(int code, Expr expr) 82 { 83 _code = code; 84 _left = expr; 85 } 86 87 public StringExpr(String value) 88 { 89 _code = CONST; 90 _value = value; 91 } 92 93 99 public StringExpr(int code, ArrayList args) 100 { 101 _code = code; 102 _args = args; 103 104 if (args.size() > 0) 105 _left = (Expr) args.get(0); 106 if (args.size() > 1) 107 _right = (Expr) args.get(1); 108 if (args.size() > 2) 109 _third = (Expr) args.get(2); 110 } 111 112 115 public boolean isString() 116 { 117 return true; 118 } 119 120 public String getValue() 121 { 122 return _value; 123 } 124 125 126 134 public String evalString(Node node, ExprEnvironment env) 135 throws XPathException 136 { 137 switch (_code) { 138 case CONST: 139 return _value; 140 141 case STRING: 142 return _left.evalString(node, env); 143 144 case CONCAT: 145 CharBuffer cb = CharBuffer.allocate(); 146 for (int i = 0; i < _args.size(); i++) 147 ((Expr) _args.get(i)).evalString(cb, node, env); 148 return cb.close(); 149 150 case SUBSTRING_BEFORE: 151 String lstr = _left.evalString(node, env); 152 String rstr = _right.evalString(node, env); 153 int index = lstr.indexOf(rstr); 154 return index > 0 ? lstr.substring(0, index) : ""; 155 156 case SUBSTRING_AFTER: 157 lstr = _left.evalString(node, env); 158 rstr = _right.evalString(node, env); 159 index = lstr.indexOf(rstr); 160 return index >= 0 ? lstr.substring(index + rstr.length()) : ""; 161 162 case NORMALIZE: 163 lstr = _left.evalString(node, env); 164 return normalize(lstr); 165 166 case TRANSLATE: 167 lstr = _left.evalString(node, env); 168 rstr = _right.evalString(node, env); 169 String tstr = _third.evalString(node, env); 170 return translate(lstr, rstr, tstr); 171 172 case FORMAT_NUMBER: 173 return _left.evalString(node, env); 174 175 case LOCAL_PART: 176 Object lobj = _left.evalObject(node, env); 177 Node nodeValue = toNode(lobj); 178 if (nodeValue != null) 179 return nodeValue.getLocalName(); 180 else 181 return ""; 182 183 case NAMESPACE: 184 lobj = _left.evalObject(node, env); 185 nodeValue = toNode(lobj); 186 if (nodeValue != null) { 187 String uri = nodeValue.getNamespaceURI(); 188 return uri != null ? uri : ""; 189 } 190 else 191 return ""; 192 193 case QNAME: 194 lobj = _left.evalObject(node, env); 195 nodeValue = toNode(lobj); 196 if (nodeValue != null) 197 return nodeValue.getNodeName(); 198 else 199 return ""; 200 201 case GENERATE_ID: 202 Iterator iter = _left.evalNodeSet(node, env); 203 return "G" + String.valueOf(System.identityHashCode(iter.next())); 204 205 case SYSTEM_PROPERTY: 206 lstr = _left.evalString(node, env); 207 if (lstr == null) 208 return ""; 209 else if (lstr.equals("xsl:version")) 210 return "1.0"; 211 else 212 return ""; 213 214 case SUBSTRING: 215 lstr = _left.evalString(node, env); 216 if (lstr == null) 217 lstr = ""; 218 double start = _right.evalNumber(node, env) - 1; 219 220 double end = lstr.length(); 221 if (_third != null) 222 end = Math.round(start) + _third.evalNumber(node, env); 223 224 if (Double.isNaN(end) || Double.isNaN(start)) { 225 start = 0; 226 end = 0; 227 } 228 229 if (start < 0) 230 start = 0; 231 else if (lstr.length() < start) 232 start = lstr.length(); 233 234 if (end < 0) 235 end = 0; 236 else if (end < start) 237 end = start; 238 else if (lstr.length() < end) 239 end = lstr.length(); 240 241 return lstr.substring((int) (start + 0.5), (int) (end + 0.5)); 242 243 default: 244 throw new RuntimeException ("unknown code: " + _code); 245 } 246 } 247 248 257 public boolean evalBoolean(Node node, ExprEnvironment env) 258 throws XPathException 259 { 260 String string = evalString(node, env); 261 262 return string != null && string.length() > 0; 263 } 264 265 274 public double evalNumber(Node node, ExprEnvironment env) 275 throws XPathException 276 { 277 return stringToNumber(evalString(node, env)); 278 } 279 280 288 public Object evalObject(Node node, ExprEnvironment env) 289 throws XPathException 290 { 291 return evalString(node, env); 292 } 293 294 298 private String normalize(String string) 299 { 300 CharBuffer result = new CharBuffer(); 301 302 int i = 0; 303 int len = string.length(); 304 for (; i < len && XmlChar.isWhitespace(string.charAt(i)); i++) { 305 } 306 307 boolean lastIsWhitespace = false; 308 for (; i < len; i++) { 309 if (XmlChar.isWhitespace(string.charAt(i))) { 310 lastIsWhitespace = true; 311 } 312 else if (lastIsWhitespace) { 313 result.append(' '); 314 result.append(string.charAt(i)); 315 lastIsWhitespace = false; 316 } 317 else 318 result.append(string.charAt(i)); 319 } 320 321 return result.toString(); 322 } 323 324 332 private String translate(String string, String from, String to) 333 { 334 CharBuffer result = new CharBuffer(); 335 336 loop: 337 for (int i = 0; i < string.length(); i++) { 338 char ch = string.charAt(i); 339 340 for (int j = 0; j < from.length(); j++) { 341 if (ch == from.charAt(j)) { 342 if (to.length() > j) 343 result.append(to.charAt(j)); 344 continue loop; 345 } 346 } 347 348 result.append(ch); 349 } 350 351 return result.toString(); 352 } 353 354 359 public String toString() 360 { 361 switch (_code) { 362 case CONST: 363 CharBuffer cb = CharBuffer.allocate(); 364 cb.append("'"); 365 for (int i = 0; i < _value.length(); i++) { 366 char ch = _value.charAt(i); 367 switch (ch) { 368 case '\n': 369 cb.append("\\n"); 370 break; 371 case '\r': 372 cb.append("\\r"); 373 break; 374 case '\\': 375 cb.append("\\\\"); 376 break; 377 case '\'': 378 cb.append("\\'\\'"); 379 break; 380 case '"': 381 cb.append("\\\""); 382 break; 383 default: 384 cb.append(ch); 385 } 386 } 387 cb.append("'"); 388 return cb.toString(); 389 390 case STRING: return "string(" + _left + ")"; 391 392 case CONCAT: 393 String result = "concat("; 394 for (int i = 0; i < _args.size(); i++) { 395 if (i > 0) 396 result = result + ", "; 397 result = result + _args.get(i); 398 } 399 return result + ")"; 400 401 case SUBSTRING_BEFORE: 402 return "substring-before(" + _left + ", " + _right + ")"; 403 404 case SUBSTRING_AFTER: 405 return "substring-after(" + _left + ", " + _right + ")"; 406 407 case NORMALIZE: 408 return "normalize-space(" + _left + ")"; 409 410 case TRANSLATE: 411 return "translate(" + _left + ", " + _right + ", " + _third + ")"; 412 413 case FORMAT_NUMBER: 414 return "format-number(" + _left + ")"; 415 416 case LOCAL_PART: 417 return "local-part(" + _left + ")"; 418 419 case NAMESPACE: 420 return "namespace-uri(" + _left + ")"; 421 422 case QNAME: 423 return "name(" + _left + ")"; 424 425 case GENERATE_ID: 426 return "generate-id(" + _left + ")"; 427 428 case SYSTEM_PROPERTY: 429 return "system-property(" + _left + ")"; 430 431 case SUBSTRING: 432 return "substring(" + _left + "," + _right + 433 (_third == null ? "" : ("," + _third)) + ")"; 434 435 case BASE_URI: 436 return "fn:base-uri(" + _left + ")"; 437 438 default: 439 return super.toString(); 440 } 441 } 442 } 443 | Popular Tags |