001: package net.sf.saxon.query;
002:
003: import net.sf.saxon.Configuration;
004: import net.sf.saxon.event.*;
005: import net.sf.saxon.om.DocumentInfo;
006: import net.sf.saxon.om.Item;
007: import net.sf.saxon.om.NodeInfo;
008: import net.sf.saxon.om.SequenceIterator;
009: import net.sf.saxon.tinytree.TinyBuilder;
010: import net.sf.saxon.trans.DynamicError;
011: import net.sf.saxon.trans.XPathException;
012: import net.sf.saxon.type.Type;
013: import net.sf.saxon.value.QNameValue;
014:
015: import javax.xml.transform.OutputKeys;
016: import javax.xml.transform.Result;
017: import javax.xml.transform.stream.StreamResult;
018: import java.io.OutputStream;
019: import java.io.OutputStreamWriter;
020: import java.io.PrintWriter;
021: import java.io.UnsupportedEncodingException;
022: import java.util.Properties;
023:
024: /**
025: * This utility class takes the result sequence produced by a query, and wraps it as
026: * an XML document. The class is never instantiated.
027: */
028: public class QueryResult {
029:
030: public static String RESULT_NS = "http://saxon.sf.net/xquery-results";
031:
032: private QueryResult() {
033: }
034:
035: /**
036: * Take the results of a query (or any other SequenceIterator) and create
037: * an XML document containing copies of all items in the sequence, suitably wrapped
038: * @param iterator The values to be wrapped
039: * @param config The Saxon configuration used to evaluate the query
040: * @return the document containing the wrapped results
041: * @throws XPathException
042: */
043:
044: public static DocumentInfo wrap(SequenceIterator iterator,
045: Configuration config) throws XPathException {
046: PipelineConfiguration pipe = config.makePipelineConfiguration();
047: TinyBuilder builder = new TinyBuilder();
048:
049: NamespaceReducer reducer = new NamespaceReducer();
050: reducer.setUnderlyingReceiver(builder);
051: Receiver tree = reducer;
052:
053: tree.setPipelineConfiguration(pipe);
054: builder.setPipelineConfiguration(pipe);
055: sendWrappedSequence(iterator, tree);
056: return (DocumentInfo) builder.getCurrentRoot();
057: }
058:
059: /**
060: * Take a sequence supplied in the form of an iterator and generate a wrapped represention of the
061: * items in the sequence, the wrapped representation being a sequence of events sent to a supplied
062: * Receiver.
063: * @param iterator the input sequence
064: * @param destination the Receiver to accept the wrapped output
065: */
066:
067: public static void sendWrappedSequence(SequenceIterator iterator,
068: Receiver destination) throws XPathException {
069: SequenceCopier.copySequence(iterator, new SequenceWrapper(
070: destination));
071: }
072:
073: /**
074: * Serialize a document containing wrapped query results (or any other document, in fact)
075: * as XML.
076: * @param node The document or element to be serialized
077: * @param destination The Result object to contain the serialized form
078: * @param outputProperties Serialization options
079: * @param config The Configuration
080: * @throws XPathException If serialization fails
081: */
082:
083: public static void serialize(NodeInfo node, Result destination,
084: Properties outputProperties, Configuration config)
085: throws XPathException {
086: PipelineConfiguration pipe = config.makePipelineConfiguration();
087: int type = node.getNodeKind();
088: if (type == Type.DOCUMENT || type == Type.ELEMENT) {
089: DocumentSender sender = new DocumentSender(node);
090: Receiver receiver = ResultWrapper.getReceiver(destination,
091: pipe, outputProperties);
092: NamespaceReducer reducer = new NamespaceReducer();
093: reducer.setUnderlyingReceiver(receiver);
094: reducer.setPipelineConfiguration(pipe);
095: sender.send(reducer);
096: } else {
097: throw new DynamicError(
098: "Node to be serialized must be a Document or Element node");
099: }
100: }
101:
102: /**
103: * Serialize an arbitrary sequence, without any special wrapping.
104: * @param results the sequence to be serialized
105: * @param config the configuration (gives access to information such as the NamePool)
106: * @param destination the output stream to which the output is to be written
107: * @param outputProps a set of serialization properties as defined in JAXP
108: * @throws XPathException if any failure occurs
109: */
110:
111: public static void serializeSequence(SequenceIterator results,
112: Configuration config, OutputStream destination,
113: Properties outputProps) throws XPathException {
114: String encoding = outputProps.getProperty(OutputKeys.ENCODING);
115: if (encoding == null) {
116: encoding = "UTF-8";
117: }
118: PrintWriter writer;
119: try {
120: writer = new PrintWriter(new OutputStreamWriter(
121: destination, encoding));
122: } catch (UnsupportedEncodingException err) {
123: throw new DynamicError(err);
124: }
125: while (true) {
126: Item item = results.next();
127: if (item == null)
128: break;
129: if (item instanceof NodeInfo) {
130: switch (((NodeInfo) item).getNodeKind()) {
131: case Type.DOCUMENT:
132: case Type.ELEMENT:
133: serialize((NodeInfo) item,
134: new StreamResult(writer), outputProps,
135: config);
136: writer.println("");
137: break;
138: case Type.ATTRIBUTE:
139: writer.println(((NodeInfo) item).getLocalPart()
140: + "=\"" + item.getStringValue() + '\"');
141: break;
142: case Type.COMMENT:
143: writer.println("<!--" + item.getStringValue()
144: + "-->");
145: break;
146: case Type.PROCESSING_INSTRUCTION:
147: writer.println("<?"
148: + ((NodeInfo) item).getLocalPart() + ' '
149: + item.getStringValue() + "?>");
150: break;
151: default:
152: writer.println(item.getStringValue());
153: }
154: } else if (item instanceof QNameValue) {
155: writer.println(((QNameValue) item).getClarkName());
156: } else {
157: writer.println(item.getStringValue());
158: }
159: }
160: writer.flush();
161: }
162:
163: // public static void main(String[] params) throws Exception {
164: // StaticQueryContext env = new StaticQueryContext(new Configuration());
165: // QueryProcessor qp = new QueryProcessor(env);
166: // XQueryExpression exp = qp.compileQuery("<a><b/></a>");
167: // SequenceIterator iter = exp.iterator(new DynamicQueryContext());
168: // NodeInfo node = (NodeInfo)iter.next();
169: // serialize(node, new SAXResult(new ExampleContentHandler()), new Properties());
170: //
171: // }
172: }
173:
174: //
175: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
176: // you may not use this file except in compliance with the License. You may obtain a copy of the
177: // License at http://www.mozilla.org/MPL/
178: //
179: // Software distributed under the License is distributed on an "AS IS" basis,
180: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
181: // See the License for the specific language governing rights and limitations under the License.
182: //
183: // The Original Code is: all this file.
184: //
185: // The Initial Developer of the Original Code is Michael H. Kay
186: //
187: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
188: //
189: // Contributor(s): none.
190: //
|