1 2 import net.sf.saxon.Configuration; 3 import net.sf.saxon.style.StandardNames; 4 import net.sf.saxon.tinytree.CharSlice; 5 import net.sf.saxon.event.*; 6 import net.sf.saxon.expr.ExpressionLocation; 7 import net.sf.saxon.om.*; 8 import net.sf.saxon.pull.PullProvider; 9 import net.sf.saxon.pull.PullPushCopier; 10 import net.sf.saxon.trans.DynamicError; 11 import net.sf.saxon.trans.SaxonErrorCode; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.value.AtomicValue; 14 15 import javax.xml.stream.*; 16 import javax.xml.transform.SourceLocator ; 17 import javax.xml.transform.TransformerException ; 18 import java.io.File ; 19 import java.io.FileInputStream ; 20 import java.io.FileOutputStream ; 21 import java.io.InputStream ; 22 import java.util.Properties ; 23 24 28 29 public class StaxBridge implements PullProvider, SaxonLocator { 30 31 private XMLStreamReader reader; 32 private StaxAttributes attributes = new StaxAttributes(); 33 private StaxNamespaces namespaces = new StaxNamespaces(); 34 private PipelineConfiguration pipe; 35 int currentEvent = START_OF_INPUT; 36 int depth = 0; 37 38 public StaxBridge() { 39 40 } 41 42 public void setInputStream(String systemId, InputStream inputStream) throws XPathException { 43 try { 44 XMLInputFactory factory = XMLInputFactory.newInstance(); 45 factory.setXMLReporter(new StaxErrorReporter()); 46 XMLStreamReader reader = factory.createXMLStreamReader(systemId, inputStream); 47 this.reader = reader; 48 } catch (XMLStreamException e) { 49 throw new DynamicError(e); 50 } 51 } 52 53 57 58 public void setPipelineConfiguration(PipelineConfiguration pipe) { 59 this.pipe = new PipelineConfiguration(pipe); 60 this.pipe.setLocationProvider(this); 61 } 62 63 66 67 public PipelineConfiguration getPipelineConfiguration() { 68 return pipe; 69 } 70 71 74 75 public NamePool getNamePool() { 76 return pipe.getConfiguration().getNamePool(); 77 } 78 79 85 86 public int next() throws XPathException { 87 if (currentEvent == START_OF_INPUT) { 88 currentEvent = START_DOCUMENT; 90 return currentEvent; 91 } 92 if (currentEvent == END_OF_INPUT || currentEvent == END_DOCUMENT) { 93 try { 94 reader.close(); 95 } catch (XMLStreamException e) { 96 } 98 return END_OF_INPUT; 99 } 100 try { 101 if (reader.hasNext()) { 102 int event = reader.next(); 103 currentEvent = translate(event); 105 } else { 106 currentEvent = END_OF_INPUT; 107 } 108 } catch (XMLStreamException e) { 109 String message = e.getMessage(); 110 if (message.startsWith("ParseError at")) { 112 int c = message.indexOf("\nMessage: "); 113 if (c > 0) { 114 message = message.substring(c+10); 115 } 116 } 117 DynamicError err = new DynamicError("Error reported by XML parser: " + message); 118 err.setErrorCode(SaxonErrorCode.SXXP0003); 119 err.setLocator(translateLocation(e.getLocation())); 120 throw err; 121 } 122 return currentEvent; 123 } 124 125 126 private int translate(int event) throws XPathException { 127 switch (event) { 129 case XMLStreamConstants.ATTRIBUTE: 130 return ATTRIBUTE; 131 case XMLStreamConstants.CDATA: 132 return TEXT; 133 case XMLStreamConstants.CHARACTERS: 134 if (depth == 0) { 135 return next(); 136 } else { 137 return TEXT; 141 } 142 case XMLStreamConstants.COMMENT: 143 return COMMENT; 144 case XMLStreamConstants.DTD: 145 return next(); 146 case XMLStreamConstants.END_DOCUMENT: 147 return END_DOCUMENT; 148 case XMLStreamConstants.END_ELEMENT: 149 depth--; 150 return END_ELEMENT; 151 case XMLStreamConstants.ENTITY_DECLARATION: 152 return next(); 153 case XMLStreamConstants.ENTITY_REFERENCE: 154 return next(); 155 case XMLStreamConstants.NAMESPACE: 156 return NAMESPACE; 157 case XMLStreamConstants.NOTATION_DECLARATION: 158 return next(); 159 case XMLStreamConstants.PROCESSING_INSTRUCTION: 160 return PROCESSING_INSTRUCTION; 161 case XMLStreamConstants.SPACE: 162 if (depth == 0) { 163 return next(); 164 } else { 165 return TEXT; 166 } 167 case XMLStreamConstants.START_DOCUMENT: 168 return next(); case XMLStreamConstants.START_ELEMENT: 171 depth++; 172 return START_ELEMENT; 173 default: 174 throw new IllegalStateException ("Unknown StAX event " + event); 175 176 177 } 178 } 179 180 187 188 public int current() { 189 return currentEvent; 190 } 191 192 206 207 public AttributeCollection getAttributes() throws XPathException { 208 return attributes; 209 } 210 211 230 231 public NamespaceDeclarations getNamespaceDeclarations() throws XPathException { 232 return namespaces; 233 } 234 235 241 242 public int skipToMatchingEnd() throws XPathException { 243 switch (currentEvent) { 244 case START_DOCUMENT: 245 currentEvent = END_DOCUMENT; 246 return currentEvent; 247 case START_ELEMENT: 248 try { 249 int skipDepth = 0; 250 while (reader.hasNext()) { 251 int event = reader.next(); 252 if (event == XMLStreamConstants.START_ELEMENT) { 253 skipDepth++; 254 } else if (event == XMLStreamConstants.END_ELEMENT) { 255 if (skipDepth-- == 0) { 256 currentEvent = END_ELEMENT; 257 return currentEvent; 258 } 259 } 260 } 261 } catch (XMLStreamException e) { 262 throw new DynamicError(e); 263 } 264 throw new IllegalStateException ( 265 "Element start has no matching element end"); 266 default: 267 throw new IllegalStateException ( 268 "Cannot call skipToMatchingEnd() except when at start of element or document"); 269 270 } 271 } 272 273 280 281 public void close() { 282 try { 283 reader.close(); 284 } catch (XMLStreamException e) { 285 } 287 } 288 289 301 302 public int getNameCode() { 303 if (currentEvent == START_ELEMENT || currentEvent == END_ELEMENT) { 304 String local = reader.getLocalName(); 305 String uri = reader.getNamespaceURI(); 306 String prefix = reader.getPrefix(); 307 if (prefix==null) { 308 prefix = ""; 309 } 310 if (uri == null) { 311 uri = ""; 312 } 313 return getNamePool().allocate(prefix, uri, local); 314 } else if (currentEvent == PROCESSING_INSTRUCTION) { 315 String local = reader.getPITarget(); 316 return getNamePool().allocate("", "", local); 317 } else { 318 throw new IllegalStateException (); 319 } 320 } 321 322 335 336 public int getFingerprint() { 337 int nc = getNameCode(); 338 if (nc == -1) { 339 return -1; 340 } else { 341 return nc & NamePool.FP_MASK; 342 } 343 } 344 345 359 360 public CharSequence getStringValue() throws XPathException { 361 switch (currentEvent) { 362 case TEXT: 363 case COMMENT: 364 return new CharSlice(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength()); 366 case PROCESSING_INSTRUCTION: 368 String s = reader.getPIData(); 369 if (s.length() > 0 && s.charAt(0) == ' ') { 372 return s.substring(1); 373 } else { 374 return s; 375 } 376 case START_ELEMENT: 377 FastStringBuffer combinedText = null; 378 try { 379 int depth = 0; 380 while (reader.hasNext()) { 381 int event = reader.next(); 382 if (event == XMLStreamConstants.CHARACTERS) { 383 if (combinedText == null) { 384 combinedText = new FastStringBuffer(1024); 385 } 386 combinedText.append( 387 reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength()); 388 } else if (event == XMLStreamConstants.START_ELEMENT) { 389 depth++; 390 } else if (event == XMLStreamConstants.END_ELEMENT) { 391 if (depth-- == 0) { 392 currentEvent = END_ELEMENT; 393 if (combinedText != null) { 394 return combinedText.condense(); 395 } else { 396 return ""; 397 } 398 } 399 } 400 } 401 } catch (XMLStreamException e) { 402 throw new DynamicError(e); 403 } 404 default: 405 throw new IllegalStateException ("getStringValue() called when current event is " + currentEvent); 406 407 } 408 } 409 410 415 416 public AtomicValue getAtomicValue() { 417 throw new IllegalStateException (); 418 } 419 420 429 430 public int getLocationId() { 431 return 0; } 433 434 442 443 public int getTypeAnnotation() { 444 return -1; 445 } 446 447 454 455 public SourceLocator getSourceLocator() { 456 return translateLocation(reader.getLocation()); 457 } 458 459 462 463 private ExpressionLocation translateLocation(Location location) { 464 ExpressionLocation loc = new ExpressionLocation(); 465 loc.setLineNumber(location.getLineNumber()); 466 loc.setColumnNumber(location.getColumnNumber()); 467 loc.setSystemId(location.getSystemId()); 468 loc.setPublicId(location.getPublicId()); 469 return loc; 470 } 471 472 475 476 private class StaxAttributes implements AttributeCollection { 477 478 482 483 public void setLocationProvider(LocationProvider provider) { 484 485 } 486 487 492 493 public int getLength() { 494 return reader.getAttributeCount(); 495 } 496 497 503 504 public int getNameCode(int index) { 505 String local = reader.getAttributeLocalName(index); 506 String uri = reader.getAttributeNamespace(index); 507 String prefix = reader.getAttributePrefix(index); 508 if (prefix == null) { 509 prefix = ""; 510 } 511 if (uri == null) { 512 uri = ""; 513 } 514 return getNamePool().allocate(prefix, uri, local); 515 } 518 519 526 527 public int getTypeAnnotation(int index) { 528 if (isId(index)) { 529 return StandardNames.XS_ID | NodeInfo.IS_DTD_TYPE; 530 } 531 return StandardNames.XDT_UNTYPED_ATOMIC; 532 } 533 534 542 543 public int getLocationId(int index) { 544 return 0; 545 } 546 547 559 560 public String getSystemId(int index) { 561 return reader.getLocation().getSystemId(); 562 } 563 564 576 577 public int getLineNumber(int index) { 578 return reader.getLocation().getLineNumber(); 579 } 580 581 590 591 public int getProperties(int index) { 592 int properties = 0; 593 if (!reader.isAttributeSpecified(index)) { 594 properties |= ReceiverOptions.DEFAULTED_ATTRIBUTE; 595 } 596 return properties; 597 } 598 599 607 608 public String getPrefix(int index) { 609 return getNamePool().getPrefix(getNameCode(index)); 610 } 611 612 619 620 public String getQName(int index) { 621 return getNamePool().getDisplayName(getNameCode(index)); 622 } 623 624 631 632 public String getLocalName(int index) { 633 return reader.getAttributeLocalName(index); 634 } 635 636 643 644 public String getURI(int index) { 645 return reader.getAttributeNamespace(index); 646 } 647 648 655 656 public int getIndex(String uri, String localname) { 657 for (int i=0; i<getLength(); i++) { 658 if (getLocalName(i) == localname && getURI(i) == uri) { 659 return i; 660 } 661 } 662 return -1; 663 } 664 665 668 669 public int getIndexByFingerprint(int fingerprint) { 670 return getIndex(getNamePool().getURI(fingerprint), getNamePool().getLocalName(fingerprint)); 671 } 672 673 676 677 public String getValueByFingerprint(int fingerprint) { 678 return getValue(getIndexByFingerprint(fingerprint)); 679 } 680 681 688 689 public String getValue(String uri, String localname) { 690 return reader.getAttributeValue(uri, localname); 691 } 692 693 700 701 public String getValue(int index) { 702 return reader.getAttributeValue(index); 703 } 704 705 708 709 public boolean isId(int index) { 710 return reader.getAttributeType(index).equals("ID"); 711 } 712 } 713 714 public class StaxNamespaces implements NamespaceDeclarations { 715 718 719 public int getLength() { 720 return reader.getNamespaceCount(); 721 } 722 723 732 733 public String getPrefix(int index) { 734 String p = reader.getNamespacePrefix(index); 735 return (p==null ? "" : p); 736 } 737 738 747 748 public String getURI(int index) { 749 String uri = reader.getNamespaceURI(index); 750 return (uri==null ? "" : uri); 751 } 752 753 766 767 public int getNamespaceCode(int index) { 768 return getNamePool().allocateNamespaceCode(getPrefix(index), getURI(index)); 769 } 770 771 780 781 public int[] getNamespaceCodes(int[] buffer) { 782 if (buffer.length < getLength()) { 783 buffer = new int[getLength()]; 784 } 785 for (int i=0; i<getLength(); i++) { 786 buffer[i] = getNamespaceCode(i); 787 } 788 return buffer; 789 } 790 791 } 792 793 804 public String getPublicId() { 805 return reader.getLocation().getPublicId(); 806 } 807 808 824 public String getSystemId() { 825 return reader.getLocation().getSystemId(); 826 } 827 828 852 public int getLineNumber() { 853 return reader.getLocation().getLineNumber(); 854 } 855 856 880 public int getColumnNumber() { 881 return reader.getLocation().getColumnNumber(); 882 } 883 884 public String getSystemId(int locationId) { 885 return getSystemId(); 886 } 887 888 public int getLineNumber(int locationId) { 889 return getLineNumber(); 890 } 891 892 895 896 private class StaxErrorReporter implements XMLReporter { 897 898 public void report(String message, String errorType, 899 Object relatedInformation, Location location) 900 throws XMLStreamException { 901 ExpressionLocation loc = translateLocation(location); 902 DynamicError err = new DynamicError("Error reported by XML parser: " + message + " (" + errorType + ')'); 903 err.setLocator(loc); 904 try { 905 pipe.getErrorListener().error(err); 906 } catch (TransformerException e) { 907 throw new XMLStreamException(e); 908 } 909 } 910 911 } 912 913 917 918 public static void main(String [] args) throws Exception { 919 for (int i=0; i<1; i++) { 920 long startTime = System.currentTimeMillis(); 921 PipelineConfiguration pipe = new Configuration().makePipelineConfiguration(); 922 StaxBridge puller = new StaxBridge(); 923 File f = new File (args[0]); 924 puller.setInputStream(f.toURI().toString(), new FileInputStream (f)); 925 XMLEmitter emitter = new XMLEmitter(); 926 emitter.setPipelineConfiguration(pipe); 927 emitter.setOutputProperties(new Properties ()); 928 if (args.length > 1) { 929 emitter.setOutputStream(new FileOutputStream (args[1])); 930 } else { 931 emitter.setOutputStream(System.out); 932 } 933 NamespaceReducer r = new NamespaceReducer(); 934 r.setUnderlyingReceiver(emitter); 935 puller.setPipelineConfiguration(pipe); 936 r.setPipelineConfiguration(pipe); 937 new PullPushCopier(puller, r).copy(); 938 System.err.println("Elapsed time: " + (System.currentTimeMillis() - startTime) + "ms"); 939 } 940 } 941 } 942 943 944 | Popular Tags |