1 3 package com.nwalsh.xalan; 4 5 import java.util.Hashtable ; 6 import org.xml.sax.*; 7 import org.xml.sax.helpers.AttributesImpl ; 8 import org.w3c.dom.*; 9 import org.w3c.dom.traversal.NodeIterator; 10 11 import javax.xml.transform.TransformerException ; 12 13 import org.apache.xpath.objects.XObject; 14 import org.apache.xpath.XPathContext; 15 import org.apache.xalan.extensions.ExpressionContext; 16 import org.apache.xml.utils.DOMBuilder; 17 import javax.xml.parsers.DocumentBuilder ; 18 import javax.xml.parsers.DocumentBuilderFactory ; 19 import javax.xml.parsers.ParserConfigurationException ; 20 import org.apache.xml.utils.QName; 21 import org.apache.xpath.DOMHelper; 22 import org.apache.xml.utils.AttList; 23 24 63 public class Table { 64 65 private static int pixelsPerInch = 96; 66 67 68 protected static Hashtable unitHash = null; 69 70 71 protected static String foURI = "http://www.w3.org/1999/XSL/Format"; 72 73 78 public Table() { 79 } 80 81 82 protected static void initializeHash() { 83 unitHash = new Hashtable (); 84 unitHash.put("in", new Float (pixelsPerInch)); 85 unitHash.put("cm", new Float (pixelsPerInch / 2.54)); 86 unitHash.put("mm", new Float (pixelsPerInch / 25.4)); 87 unitHash.put("pc", new Float ((pixelsPerInch / 72) * 12)); 88 unitHash.put("pt", new Float (pixelsPerInch / 72)); 89 unitHash.put("px", new Float (1)); 90 } 91 92 93 public static void setPixelsPerInch(int value) { 94 if (value > 0) { 95 pixelsPerInch = value; 96 initializeHash(); 97 } 98 } 99 100 101 public int getPixelsPerInch() { 102 return pixelsPerInch; 103 } 104 105 111 public static int convertLength(String length) { 112 int sign = 1; 114 String digits = ""; 115 String units = ""; 116 char lench[] = length.toCharArray(); 117 float flength = 0; 118 boolean done = false; 119 int pos = 0; 120 float factor = 1; 121 int pixels = 0; 122 123 if (unitHash == null) { 124 initializeHash(); 125 } 126 127 if (lench[pos] == '+' || lench[pos] == '-') { 128 if (lench[pos] == '-') { 129 sign = -1; 130 } 131 pos++; 132 } 133 134 while (!done) { 135 if (pos >= lench.length) { 136 done = true; 137 } else { 138 if ((lench[pos] > '9' || lench[pos] < '0') && lench[pos] != '.') { 139 done = true; 140 units = length.substring(pos); 141 } else { 142 digits += lench[pos++]; 143 } 144 } 145 } 146 147 try { 148 flength = Float.parseFloat(digits); 149 } catch (NumberFormatException e) { 150 System.out.println(digits + " is not a number; 1 used instead."); 151 flength = 1; 152 } 153 154 Float f = null; 155 156 if (!units.equals("")) { 157 f = (Float ) unitHash.get(units); 158 if (f == null) { 159 System.out.println(units + " is not a known unit; 1 used instead."); 160 factor = 1; 161 } else { 162 factor = f.floatValue(); 163 } 164 } else { 165 factor = 1; 166 } 167 168 f = new Float (flength * factor); 169 170 pixels = f.intValue() * sign; 171 172 return pixels; 173 } 174 175 222 223 public DocumentFragment adjustColumnWidths (ExpressionContext context, 224 NodeIterator xalanNI) { 225 226 int nominalWidth = convertLength(Params.getString(context, 227 "nominal.table.width")); 228 String tableWidth = Params.getString(context, "table.width"); 229 String styleType = Params.getString(context, "stylesheet.result.type"); 230 boolean foStylesheet = styleType.equals("fo"); 231 232 DocumentFragment xalanRTF = (DocumentFragment) xalanNI.nextNode(); 233 Element colgroup = (Element) xalanRTF.getFirstChild(); 234 235 237 Node firstCol = null; 238 if (colgroup.getLocalName().equals("colgroup")) { 240 firstCol = colgroup.getFirstChild(); 241 } else { 242 firstCol = colgroup; 243 } 244 245 Node child = firstCol; 247 int numColumns = 0; 248 while (child != null) { 249 if (child.getNodeType() == Node.ELEMENT_NODE 250 && (child.getNodeName().equals("col") 251 || (child.getNamespaceURI().equals(foURI) 252 && child.getLocalName().equals("table-column")))) { 253 numColumns++; 254 } 255 256 child = child.getNextSibling(); 257 } 258 259 String widths[] = new String [numColumns]; 260 Element columns[] = new Element[numColumns]; 261 int colnum = 0; 262 263 child = firstCol; 264 while (child != null) { 265 if (child.getNodeType() == Node.ELEMENT_NODE 266 && (child.getNodeName().equals("col") 267 || (child.getNamespaceURI().equals(foURI) 268 && child.getLocalName().equals("table-column")))) { 269 Element col = (Element) child; 270 271 columns[colnum] = col; 272 273 if (foStylesheet) { 274 if (col.getAttribute("column-width") == null) { 275 widths[colnum] = "1*"; 276 } else { 277 widths[colnum] = col.getAttribute("column-width"); 278 } 279 } else { 280 if (col.getAttribute("width") == null) { 281 widths[colnum] = "1*"; 282 } else { 283 widths[colnum] = col.getAttribute("width"); 284 } 285 } 286 287 colnum++; 288 } 289 child = child.getNextSibling(); 290 } 291 292 float relTotal = 0; 293 float relParts[] = new float[numColumns]; 294 295 float absTotal = 0; 296 float absParts[] = new float[numColumns]; 297 298 for (int count = 0; count < numColumns; count++) { 299 String width = widths[count]; 300 int pos = width.indexOf("*"); 301 if (pos >= 0) { 302 String relPart = width.substring(0, pos); 303 String absPart = width.substring(pos+1); 304 305 try { 306 float rel = Float.parseFloat(relPart); 307 relTotal += rel; 308 relParts[count] = rel; 309 } catch (NumberFormatException e) { 310 System.out.println(relPart + " is not a valid relative unit."); 311 } 312 313 int pixels = 0; 314 if (absPart != null && !absPart.equals("")) { 315 pixels = convertLength(absPart); 316 } 317 318 absTotal += pixels; 319 absParts[count] = pixels; 320 } else { 321 relParts[count] = 0; 322 323 int pixels = 0; 324 if (width != null && !width.equals("")) { 325 pixels = convertLength(width); 326 } 327 328 absTotal += pixels; 329 absParts[count] = pixels; 330 } 331 } 332 333 345 if (relTotal == 0) { 346 for (int count = 0; count < numColumns; count++) { 347 Float f = new Float (absParts[count]); 348 if (foStylesheet) { 349 int pixels = f.intValue(); 350 float inches = (float) pixels / pixelsPerInch; 351 widths[count] = inches + "in"; 352 } else { 353 widths[count] = Integer.toString(f.intValue()); 354 } 355 } 356 } else if (absTotal == 0) { 357 for (int count = 0; count < numColumns; count++) { 358 float rel = relParts[count] / relTotal * 100; 359 Float f = new Float (rel); 360 widths[count] = Integer.toString(f.intValue()); 361 } 362 widths = correctRoundingError(widths); 363 } else { 364 int pixelWidth = nominalWidth; 365 366 if (tableWidth.indexOf("%") <= 0) { 367 pixelWidth = convertLength(tableWidth); 368 } 369 370 if (pixelWidth <= absTotal) { 371 System.out.println("Table is wider than table width."); 372 } else { 373 pixelWidth -= absTotal; 374 } 375 376 absTotal = 0; 377 for (int count = 0; count < numColumns; count++) { 378 float rel = relParts[count] / relTotal * pixelWidth; 379 relParts[count] = rel + absParts[count]; 380 absTotal += rel + absParts[count]; 381 } 382 383 if (tableWidth.indexOf("%") <= 0) { 384 for (int count = 0; count < numColumns; count++) { 385 Float f = new Float (relParts[count]); 386 if (foStylesheet) { 387 int pixels = f.intValue(); 388 float inches = (float) pixels / pixelsPerInch; 389 widths[count] = inches + "in"; 390 } else { 391 widths[count] = Integer.toString(f.intValue()); 392 } 393 } 394 } else { 395 for (int count = 0; count < numColumns; count++) { 396 float rel = relParts[count] / absTotal * 100; 397 Float f = new Float (rel); 398 widths[count] = Integer.toString(f.intValue()); 399 } 400 widths = correctRoundingError(widths); 401 } 402 } 403 404 406 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); 407 DocumentBuilder docBuilder = null; 408 409 try { 410 docBuilder = docFactory.newDocumentBuilder(); 411 } catch (ParserConfigurationException e) { 412 System.out.println("PCE!"); 413 return xalanRTF; 414 } 415 Document doc = docBuilder.newDocument(); 416 DocumentFragment df = doc.createDocumentFragment(); 417 DOMBuilder rtf = new DOMBuilder(doc, df); 418 419 try { 420 String ns = colgroup.getNamespaceURI(); 421 String localName = colgroup.getLocalName(); 422 String name = colgroup.getTagName(); 423 424 if (colgroup.getLocalName().equals("colgroup")) { 425 rtf.startElement(ns, localName, name, 426 copyAttributes(colgroup)); 427 } 428 429 for (colnum = 0; colnum < numColumns; colnum++) { 430 Element col = columns[colnum]; 431 432 NamedNodeMap domAttr = col.getAttributes(); 433 434 AttributesImpl attr = new AttributesImpl (); 435 for (int acount = 0; acount < domAttr.getLength(); acount++) { 436 Node a = domAttr.item(acount); 437 String a_ns = a.getNamespaceURI(); 438 String a_localName = a.getLocalName(); 439 440 if ((foStylesheet && !a_localName.equals("column-width")) 441 || !a_localName.equalsIgnoreCase("width")) { 442 attr.addAttribute(a.getNamespaceURI(), 443 a.getLocalName(), 444 a.getNodeName(), 445 "CDATA", 446 a.getNodeValue()); 447 } 448 } 449 450 if (foStylesheet) { 451 attr.addAttribute("", "column-width", "column-width", "CDATA", widths[colnum]); 452 } else { 453 attr.addAttribute("", "width", "width", "CDATA", widths[colnum]); 454 } 455 456 rtf.startElement(col.getNamespaceURI(), 457 col.getLocalName(), 458 col.getTagName(), 459 attr); 460 rtf.endElement(col.getNamespaceURI(), 461 col.getLocalName(), 462 col.getTagName()); 463 } 464 465 if (colgroup.getLocalName().equals("colgroup")) { 466 rtf.endElement(ns, localName, name); 467 } 468 } catch (SAXException se) { 469 System.out.println("SE!"); 470 return xalanRTF; 471 } 472 473 return df; 474 } 475 476 private Attributes copyAttributes(Element node) { 477 AttributesImpl attrs = new AttributesImpl (); 478 NamedNodeMap nnm = node.getAttributes(); 479 for (int count = 0; count < nnm.getLength(); count++) { 480 Attr attr = (Attr) nnm.item(count); 481 String name = attr.getName(); 482 if (name.startsWith("xmlns:") || name.equals("xmlns")) { 483 } else { 485 attrs.addAttribute(attr.getNamespaceURI(), attr.getName(), 486 attr.getName(), "CDATA", attr.getValue()); 487 } 488 } 489 return attrs; 490 } 491 492 496 protected String [] correctRoundingError(String widths[]) { 497 int totalWidth = 0; 498 499 for (int count = 0; count < widths.length; count++) { 500 try { 501 int width = Integer.parseInt(widths[count]); 502 totalWidth += width; 503 } catch (NumberFormatException nfe) { 504 } 506 } 507 508 float totalError = 100 - totalWidth; 509 float columnError = totalError / widths.length; 510 float error = 0; 511 512 for (int count = 0; count < widths.length; count++) { 513 try { 514 int width = Integer.parseInt(widths[count]); 515 error = error + columnError; 516 if (error >= 1.0) { 517 int adj = (int) Math.round(Math.floor(error)); 518 error = error - (float) Math.floor(error); 519 width = width + adj; 520 widths[count] = Integer.toString(width) + "%"; 521 } else { 522 widths[count] = Integer.toString(width) + "%"; 523 } 524 } catch (NumberFormatException nfe) { 525 } 527 } 528 529 return widths; 530 } 531 } 532 | Popular Tags |