1 package com.icl.saxon.output; 2 import com.icl.saxon.*; 3 import com.icl.saxon.charcode.*; 4 import com.icl.saxon.om.Namespace; 5 import com.icl.saxon.om.NamePool; 6 import org.xml.sax.Attributes ; 7 import org.xml.sax.Locator ; 8 import java.io.*; 9 import java.util.*; 10 11 import javax.xml.transform.Result ; 12 import javax.xml.transform.OutputKeys ; 13 import javax.xml.transform.TransformerException ; 14 import javax.xml.transform.stream.StreamResult ; 15 16 20 21 public class XMLEmitter extends Emitter 22 { 23 protected CharacterSet characterSet = null; 24 25 protected boolean empty = true; 26 protected boolean escaping = true; 27 protected boolean openStartTag = false; 28 protected boolean declarationIsWritten = false; 29 30 protected boolean preferHex = false; 31 32 protected int lastNameCode = -1; 34 protected String lastDisplayName; 35 protected String lastPrefix; 36 protected String lastURI; 37 38 static boolean[] specialInText; static boolean[] specialInAtt; 42 static { 43 specialInText = new boolean[128]; 44 for (int i=0; i<=127; i++) specialInText[i] = false; 45 specialInText['\r'] = true; 46 specialInText['<'] = true; 47 specialInText['>'] = true; 48 specialInText['&'] = true; 49 50 specialInAtt = new boolean[128]; 51 for (int i=0; i<=127; i++) specialInAtt[i] = false; 52 specialInAtt['\r'] = true; 53 specialInAtt['\n'] = true; 54 specialInAtt['\t'] = true; 55 specialInAtt['<'] = true; 56 specialInAtt['>'] = true; 57 specialInAtt['&'] = true; 58 specialInAtt['\"'] = true; 59 } 60 61 64 65 public void setDocumentLocator(Locator locator) {} 66 67 68 71 72 public void startDocument () throws TransformerException 73 { 74 if (characterSet==null) characterSet = new UnicodeCharacterSet(); 75 writeDeclaration(); 76 empty = true; 77 String rep = outputProperties.getProperty(SaxonOutputKeys.CHARACTER_REPRESENTATION); 78 if (rep!=null) { 79 preferHex = (rep.trim().equalsIgnoreCase("hex")); 80 } 81 } 82 83 86 87 public void writeDeclaration() throws TransformerException { 88 if (declarationIsWritten) return; 89 declarationIsWritten = true; 90 try { 91 92 String omit = outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION); 93 if (omit==null) omit = "no"; 94 95 String version = outputProperties.getProperty(OutputKeys.VERSION); 96 if (version==null) version = "1.0"; 97 98 String encoding = outputProperties.getProperty(OutputKeys.ENCODING); 99 if (encoding==null || encoding.equalsIgnoreCase("utf8")) { 100 encoding = "utf-8"; 101 } 102 103 if (!(encoding.equalsIgnoreCase("utf-8"))) { 104 omit = "no"; 105 } 106 107 String standalone = outputProperties.getProperty(OutputKeys.STANDALONE); 108 109 if (omit.equals("no")) { 110 writer.write("<?xml version=\"" + version + "\" " + 111 "encoding=\"" + encoding + "\"" + 112 (standalone!=null ? (" standalone=\"" + standalone + "\"") : "") + 113 "?>"); 114 } 117 } catch (java.io.IOException err) { 118 throw new TransformerException (err); 119 } 120 } 121 122 123 126 127 boolean docTypeWritten = false; 128 protected void writeDocType(String type, String systemId, String publicId) throws TransformerException { 129 if (docTypeWritten) return; 130 docTypeWritten = true; 131 try { 132 writer.write("\n<!DOCTYPE " + type + "\n"); 133 if (systemId!=null && publicId==null) { 134 writer.write(" SYSTEM \"" + systemId + "\">\n"); 135 } else if (systemId==null && publicId!=null) { writer.write(" PUBLIC \"" + publicId + "\">\n"); 137 } else { 138 writer.write(" PUBLIC \"" + publicId + "\" \"" + systemId + "\">\n"); 139 } 140 } catch (java.io.IOException err) { 141 throw new TransformerException (err); 142 } 143 } 144 145 148 149 public void endDocument () throws TransformerException 150 { 151 try { 152 writer.flush(); 153 } catch (java.io.IOException err) { 154 throw new TransformerException (err); 155 } 156 } 157 158 161 162 public void startElement (int nameCode, Attributes attributes, 163 int[] namespaces, int nscount) throws TransformerException 164 { 165 String prefix; 166 String uri; 167 String displayName; 168 169 if (nameCode==lastNameCode) { 170 prefix = lastPrefix; 171 uri = lastURI; 172 displayName = lastDisplayName; 173 } else { 174 prefix = namePool.getPrefix(nameCode); 175 uri = namePool.getURI(nameCode); 176 displayName = namePool.getDisplayName(nameCode); 177 178 lastNameCode = nameCode; 179 lastDisplayName = displayName; 180 lastPrefix = prefix; 181 lastURI = uri; 182 } 183 184 try { 185 if (empty) { 186 String systemId = outputProperties.getProperty(OutputKeys.DOCTYPE_SYSTEM); 187 String publicId = outputProperties.getProperty(OutputKeys.DOCTYPE_PUBLIC); 188 if (systemId!=null) { 189 writeDocType(displayName, systemId, publicId); 190 } 191 empty = false; 192 } 193 if (openStartTag) { 194 closeStartTag(nameCode, false); 195 } 196 writer.write('<'); 197 testCharacters(displayName); 198 writer.write(displayName); 199 200 202 for (int n=0; n<nscount; n++) { 203 writer.write(' '); 204 String nsprefix = namePool.getPrefixFromNamespaceCode(namespaces[n]); 205 String nsuri = namePool.getURIFromNamespaceCode(namespaces[n]); 206 207 if (nsprefix.equals("")) { 208 writeAttribute(nameCode, "xmlns", "CDATA", nsuri); 209 } else { 210 writeAttribute(nameCode, "xmlns:" + nsprefix, "CDATA", nsuri); 211 } 212 213 } 214 215 217 for (int i=0; i<attributes.getLength(); i++) { 218 writer.write(' '); 219 writeAttribute( 220 nameCode, 221 attributes.getQName(i), 222 attributes.getType(i), 223 attributes.getValue(i)); 224 } 225 openStartTag = true; 226 227 } catch (java.io.IOException err) { 228 throw new TransformerException (err); 229 } 230 } 231 232 protected void closeStartTag(int nameCode, boolean emptyTag) throws TransformerException { 233 try { 234 if (openStartTag) { 235 if (emptyTag) { 236 writer.write(emptyElementTagCloser(nameCode)); 237 } else { 238 writer.write('>'); 239 } 240 openStartTag = false; 241 } 242 } catch (java.io.IOException err) { 243 throw new TransformerException (err); 244 } 245 } 246 247 250 251 protected String emptyElementTagCloser(int nameCode) { 252 return "/>"; 253 } 254 255 259 260 char[] attbuff1 = new char[256]; 261 protected void writeAttribute(int elCode, String attname, String type, String value) throws TransformerException { 262 try { 263 testCharacters(attname); 264 writer.write(attname); 265 if (type.equals("NO-ESC")) { 266 writer.write('='); 268 char delimiter = (value.indexOf('"') >= 0 ? '\'' : '"'); 269 writer.write(delimiter); 270 writer.write(value); 271 writer.write(delimiter); 272 } else { 273 writer.write("=\""); 274 int len = value.length(); 275 if (len > attbuff1.length) { 276 attbuff1 = new char[len]; 277 } 278 value.getChars(0, len, attbuff1, 0); 279 writeEscape(attbuff1, 0, len, true); 280 writer.write('\"'); 281 } 282 } catch (java.io.IOException err) { 283 throw new TransformerException (err); 284 } 285 } 286 287 288 291 292 protected void testCharacters(String name) throws TransformerException { 293 for (int i=name.length()-1; i>=0; i--) { 294 if (!characterSet.inCharset(name.charAt(i))) { 295 throw new TransformerException ("Invalid character in output name (" + name + ")"); 296 } 297 } 298 } 299 300 protected boolean testCharacters(char[] array, int start, int len) 301 { 303 for (int i=start; i<len; i++) { 304 if (!characterSet.inCharset(array[i])) { 305 return false; 307 } 308 } 309 return true; 310 } 311 312 315 316 public void endElement (int nameCode) throws TransformerException 317 { 318 try { 319 if (openStartTag) { 320 closeStartTag(nameCode, true); 321 } else { 322 String displayName; 323 if (nameCode==lastNameCode) { 324 displayName = lastDisplayName; 325 } else { 326 displayName = namePool.getDisplayName(nameCode); 327 } 328 writer.write("</"); 329 writer.write(displayName); 330 writer.write('>'); 331 } 332 } catch (java.io.IOException err) { 333 throw new TransformerException (err); 334 } 335 } 336 337 340 341 public void characters (char[] ch, int start, int length) throws TransformerException 342 { 343 try { 344 if (openStartTag) { 345 closeStartTag(-1, false); 346 } 347 if (!escaping) { 348 if (testCharacters(ch, start, length)) { 349 writer.write(ch, start, length); 350 } else { 351 writeEscape(ch, start, length, false); 353 } 354 } else { 355 writeEscape(ch, start, length, false); 356 } 357 } catch (java.io.IOException err) { 358 throw new TransformerException (err); 359 } 360 } 361 362 363 366 367 public void processingInstruction (String target, String data) 368 throws TransformerException 369 { 370 try { 371 if (openStartTag) { 372 closeStartTag(-1, false); 373 } 374 writer.write("<?" + target + (data.length()>0 ? ' ' + data : "") + "?>"); 375 } catch (java.io.IOException err) { 376 throw new TransformerException (err); 377 } 378 } 379 380 388 389 protected void writeEscape(char ch[], int start, int length, boolean inAttribute) 390 throws java.io.IOException { 391 int segstart = start; 392 boolean[] specialChars = (inAttribute ? specialInAtt : specialInText); 393 394 while (segstart < start+length) { 395 int i = segstart; 396 397 while (i < start+length && 399 (ch[i]<128 ? !specialChars[ch[i]] : characterSet.inCharset(ch[i]))) { 400 i++; 401 } 402 403 writer.write(ch, segstart, i-segstart); 405 406 if (i >= start+length) return; 408 409 if (ch[i]>127) { 410 411 413 int charval; 414 415 422 if (ch[i]>=55296 && ch[i]<=56319) { 423 charval = (((int)ch[i] - 55296) * 1024) + ((int)ch[i+1] - 56320) + 65536; 425 i++; 426 } else { 427 charval = (int)ch[i]; 428 } 429 430 outputCharacterReference(charval); 431 432 } else { 433 434 436 if (ch[i]=='<') { 437 writer.write("<"); 438 } else if (ch[i]=='>') { 439 writer.write(">"); 440 } else if (ch[i]=='&') { 441 writer.write("&"); 442 } else if (ch[i]=='\"') { 443 writer.write("""); 444 } else if (ch[i]=='\n') { 445 writer.write("
"); 446 } else if (ch[i]=='\r') { 447 writer.write("
"); 448 } else if (ch[i]=='\t') { 449 writer.write("	"); 450 } 451 } 452 segstart = ++i; 453 } 454 } 455 456 459 460 private char[] charref = new char[10]; 461 protected void outputCharacterReference(int charval) throws java.io.IOException { 462 if (preferHex) { 463 int o = 0; 464 charref[o++]='&'; 465 charref[o++]='#'; 466 charref[o++]='x'; 467 String code = Integer.toHexString(charval); 468 int len = code.length(); 469 for (int k=0; k<len; k++) { 470 charref[o++]=code.charAt(k); 471 } 472 charref[o++]=';'; 473 writer.write(charref, 0, o); 474 } else { 475 int o = 0; 476 charref[o++]='&'; 477 charref[o++]='#'; 478 String code = Integer.toString(charval); 479 int len = code.length(); 480 for (int k=0; k<len; k++) { 481 charref[o++]=code.charAt(k); 482 } 483 charref[o++]=';'; 484 writer.write(charref, 0, o); 485 } 486 } 487 488 491 492 public void setEscaping(boolean escaping) { 493 this.escaping = escaping; 494 } 495 496 499 500 public void comment (char ch[], int start, int length) throws TransformerException 501 { 502 try { 503 if (openStartTag) { 504 closeStartTag(-1, false); 505 } 506 writer.write("<!--"); 507 writer.write(ch, start, length); 508 writer.write("-->"); 509 } catch (java.io.IOException err) { 510 throw new TransformerException (err); 511 } 512 } 513 514 517 518 public void setResult(Result result) { 519 if (!(result instanceof StreamResult )) { 520 throw new IllegalArgumentException ("Destination for XMLEmitter must be a StreamResult"); 521 } 522 writer = ((StreamResult )result).getWriter(); 523 if (writer==null) { 524 throw new IllegalArgumentException ("No writer supplied"); 525 } 526 } 528 529 532 533 public void setOutputProperties(Properties details) { 534 characterSet = CharacterSetFactory.getCharacterSet(details); 535 super.setOutputProperties(details); 536 } 537 538 541 542 public void setUnparsedEntity(String name, String uri) throws TransformerException { 543 } 544 545 546 } 547 548 | Popular Tags |