/** * Run the query in pull mode. * * <p> * * <p>For maximum effect this method should be used when lazyConstructionMode has been set in the * Configuration. * * <p> * * <p><b>Note: this method usually has very similar performance to the {@link * #run(DynamicQueryContext,javax.xml.transform.Result,java.util.Properties)} method (which does * the same thing), but sometimes it is significantly slower. Therefore, the run() method is * preferred.</b> * * @param dynamicEnv the dynamic context for query evaluation * @param destination the destination of the query results * @param outputProperties the serialization parameters * @see Configuration#setLazyConstructionMode(boolean) */ public void pull(DynamicQueryContext dynamicEnv, Result destination, Properties outputProperties) throws XPathException { if (isUpdating) { throw new XPathException("Cannot call pull() on an updating query"); } Configuration config = dynamicEnv.getConfiguration(); try { Controller controller = newController(); // initializeController(dynamicEnv, controller); EventIterator iter = iterateEvents(controller, dynamicEnv); // iter = new Decomposer(iter, config); Properties actualProperties = validateOutputProperties(controller, outputProperties); SerializerFactory sf = config.getSerializerFactory(); PipelineConfiguration pipe = config.makePipelineConfiguration(); pipe.setSerializing(true); Receiver receiver = sf.getReceiver(destination, pipe, actualProperties); receiver = new NamespaceReducer(receiver); if ("yes".equals(actualProperties.getProperty(SaxonOutputKeys.WRAP))) { receiver = new SequenceWrapper(receiver); // receiver = new TracingFilter(receiver); } else { receiver = new TreeReceiver(receiver); } EventIteratorToReceiver.copy(iter, (SequenceReceiver) receiver); } catch (XPathException err) { config.reportFatalError(err); throw err; } }
/** * Notify a namespace. Namespaces are notified <b>after</b> the startElement event, and before any * children for the element. */ public void namespace(int namespaceCode, int properties) throws XPathException { if (namespaceCode == NamespaceConstant.XML_NAMESPACE_CODE) { return; } NamePool pool = pipe.getConfiguration().getNamePool(); String prefix = pool.getPrefixFromNamespaceCode(namespaceCode); String uri = pool.getURIFromNamespaceCode(namespaceCode); if ((!undeclareNamespaces) && "".equals(uri) && !("".equals(prefix))) { // This is a namespace undeclaration, but the ContentHandler doesn't want to know about // undeclarations return; } try { handler.startPrefixMapping(prefix, uri); namespaceStack.push(prefix); } catch (SAXException err) { handleSAXException(err); } }
/** * Notify the start of the content, that is, the completion of all attributes and namespaces. Note * that the initial receiver of output from XSLT instructions will not receive this event, it has * to detect it itself. Note that this event is reported for every element even if it has no * attributes, no namespaces, and no content. */ public void startContent() throws XPathException { try { NamePool namePool = pipe.getConfiguration().getNamePool(); if (depth > 0 || !requireWellFormed) { String uri = namePool.getURI(pendingElement); String localName = namePool.getLocalName(pendingElement); String qname = namePool.getDisplayName(pendingElement); handler.startElement(uri, localName, qname, pendingAttributes); elementStack.push(uri); elementStack.push(localName); elementStack.push(qname); pendingAttributes.clear(); pendingElement = -1; } } catch (SAXException err) { handleSAXException(err); } }
protected Receiver createXMLSerializer( Emitter emitter, Properties props, PipelineConfiguration pipe, ProxyReceiver normalizer, CharacterMapExpander characterMapExpander) throws XPathException { Receiver target; target = emitter; if ("1.0".equals(props.getProperty(OutputKeys.VERSION)) && pipe.getConfiguration().getXMLVersion() == Configuration.XML11) { // Check result meets XML 1.0 constraints if configuration allows XML 1.1 input but // this result document must conform to 1.0 ProxyReceiver in = newXML10ContentChecker(pipe, props); in.setUnderlyingReceiver(target); target = in; } if ("yes".equals(props.getProperty(OutputKeys.INDENT))) { ProxyReceiver in = newXMLIndenter(pipe, props); in.setUnderlyingReceiver(target); target = in; } if (normalizer != null) { normalizer.setUnderlyingReceiver(target); target = normalizer; } if (characterMapExpander != null) { characterMapExpander.setUnderlyingReceiver(target); target = characterMapExpander; } String cdataElements = props.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS); if (cdataElements != null && cdataElements.length() > 0) { ProxyReceiver filter = newCDATAFilter(pipe, props); filter.setUnderlyingReceiver(target); target = filter; } return target; }
/** * Get a Receiver that wraps a given Result object. Saxon calls this method to construct a * serialization pipeline. The method can be overridden in a subclass; alternatively, the subclass * can override the various methods used to instantiate components of the serialization pipeline. * * @param result The final destination of the serialized output. Usually a StreamResult, but other * kinds of Result are possible. * @param pipe The PipelineConfiguration. * @param props The serialization properties */ public Receiver getReceiver(Result result, PipelineConfiguration pipe, Properties props) throws XPathException { if (result instanceof Emitter) { ((Emitter) result).setOutputProperties(props); return (Emitter) result; } else if (result instanceof Receiver) { Receiver receiver = (Receiver) result; receiver.setSystemId(result.getSystemId()); receiver.setPipelineConfiguration(pipe); return receiver; } else if (result instanceof SAXResult) { ContentHandlerProxy proxy = newContentHandlerProxy(); proxy.setUnderlyingContentHandler(((SAXResult) result).getHandler()); proxy.setPipelineConfiguration(pipe); proxy.setOutputProperties(props); if ("yes".equals(props.getProperty(SaxonOutputKeys.SUPPLY_SOURCE_LOCATOR))) { if (pipe.getConfiguration().isCompileWithTracing()) { pipe.getController().addTraceListener(proxy.getTraceListener()); } else { DynamicError de = new DynamicError( "Cannot use saxon:supply-source-locator unless tracing was enabled at compile time"); de.setErrorCode(SaxonErrorCode.SXSE0002); throw de; } } proxy.open(); return proxy; } else if (result instanceof StreamResult) { // The "target" is the start of the output pipeline, the Receiver that // instructions will actually write to (except that other things like a // NamespaceReducer may get added in front of it). The "emitter" is the // last thing in the output pipeline, the Receiver that actually generates // characters or bytes that are written to the StreamResult. Receiver target; String method = props.getProperty(OutputKeys.METHOD); if (method == null) { target = newUncommittedSerializer(result, props); target.setPipelineConfiguration(pipe); return target; } Emitter emitter; CharacterMapExpander characterMapExpander = null; String useMaps = props.getProperty(SaxonOutputKeys.USE_CHARACTER_MAPS); if (useMaps != null) { Controller controller = (pipe == null ? null : pipe.getController()); if (controller == null) { DynamicError de = new DynamicError("Cannot use character maps in an environment with no Controller"); de.setErrorCode(SaxonErrorCode.SXSE0001); throw de; } characterMapExpander = controller.makeCharacterMapExpander(useMaps, this); characterMapExpander.setPipelineConfiguration(pipe); } ProxyReceiver normalizer = null; String normForm = props.getProperty(SaxonOutputKeys.NORMALIZATION_FORM); if (normForm != null && !normForm.equals("none")) { normalizer = newUnicodeNormalizer(pipe, props); } if ("html".equals(method)) { emitter = newHTMLEmitter(); emitter.setPipelineConfiguration(pipe); target = createHTMLSerializer(emitter, props, pipe, characterMapExpander, normalizer); } else if ("xml".equals(method)) { emitter = newXMLEmitter(); emitter.setPipelineConfiguration(pipe); target = createXMLSerializer(emitter, props, pipe, normalizer, characterMapExpander); } else if ("xhtml".equals(method)) { emitter = newXHTMLEmitter(); emitter.setPipelineConfiguration(pipe); target = createXHTMLSerializer(emitter, props, pipe, normalizer, characterMapExpander); } else if ("text".equals(method)) { emitter = newTEXTEmitter(); emitter.setPipelineConfiguration(pipe); target = createTextSerializer(emitter, characterMapExpander, normalizer); } else { Receiver userReceiver; if (pipe == null) { throw new DynamicError("Unsupported serialization method " + method); } else { // See if this output method is recognized by the Configuration userReceiver = pipe.getConfiguration().makeEmitter(method, pipe.getController()); userReceiver.setPipelineConfiguration(pipe); if (userReceiver instanceof ContentHandlerProxy && "yes".equals(props.getProperty(SaxonOutputKeys.SUPPLY_SOURCE_LOCATOR))) { if (pipe.getConfiguration().isCompileWithTracing()) { pipe.getController() .addTraceListener(((ContentHandlerProxy) userReceiver).getTraceListener()); } else { DynamicError de = new DynamicError( "Cannot use saxon:supply-source-locator unless tracing was enabled at compile time"); de.setErrorCode(SaxonErrorCode.SXSE0002); throw de; } } target = userReceiver; if (userReceiver instanceof Emitter) { emitter = (Emitter) userReceiver; } else { return userReceiver; } } } emitter.setOutputProperties(props); StreamResult sr = (StreamResult) result; emitter.setStreamResult(sr); return target; } else { if (pipe != null) { // try to find an external object model that knows this kind of Result List externalObjectModels = pipe.getConfiguration().getExternalObjectModels(); for (int m = 0; m < externalObjectModels.size(); m++) { ExternalObjectModel model = (ExternalObjectModel) externalObjectModels.get(m); Receiver builder = model.getDocumentBuilder(result); if (builder != null) { builder.setSystemId(result.getSystemId()); builder.setPipelineConfiguration(pipe); return builder; } } } } throw new IllegalArgumentException("Unknown type of result: " + result.getClass()); }
/** Get the pipeline configuration */ public Configuration getConfiguration() { return pipe.getConfiguration(); }
/** Set the pipeline configuration */ public void setPipelineConfiguration(PipelineConfiguration pipe) { this.pipe = pipe; this.locationProvider = pipe.getLocationProvider(); }