001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.event.SequenceReceiver;
004: import net.sf.saxon.expr.StaticContext;
005: import net.sf.saxon.expr.XPathContext;
006: import net.sf.saxon.om.Item;
007: import net.sf.saxon.om.NodeInfo;
008: import net.sf.saxon.om.Validation;
009: import net.sf.saxon.style.ExpressionContext;
010: import net.sf.saxon.trace.Location;
011: import net.sf.saxon.trans.DynamicError;
012: import net.sf.saxon.trans.StaticError;
013: import net.sf.saxon.trans.XPathException;
014: import net.sf.saxon.value.StringValue;
015:
016: import javax.xml.transform.OutputKeys;
017: import javax.xml.transform.stream.StreamResult;
018: import java.io.StringWriter;
019: import java.util.Properties;
020:
021: /**
022: * This class implements the saxon:serialize() extension function,
023: * which is specially-recognized by the system because it needs access
024: * to parts of the static context
025: */
026:
027: public class Serialize extends SystemFunction implements XSLTFunction {
028:
029: Properties outputProperties;
030: private transient boolean checked = false;
031:
032: // the second time checkArguments is called, it's a global check so the static context is inaccurate
033:
034: /**
035: * Method supplied by each class of function to check arguments during parsing, when all
036: * the argument expressions have been read
037: */
038:
039: public void checkArguments(StaticContext env) throws XPathException {
040: if (checked)
041: return;
042: checked = true;
043: super .checkArguments(env);
044: if (env instanceof ExpressionContext) {
045: // We're in XSLT
046:
047: // We require the output format name to be known at compile time. If we allowed it
048: // to be dynamic, we would not only need to save the namespace context, but also to
049: // save details of all xsl:output declarations for use at run-time.
050:
051: if (!(argument[1] instanceof StringValue)) {
052: throw new StaticError(
053: "Second argument of saxon:serialize must be known at compile time");
054: }
055: String format = ((StringValue) argument[1])
056: .getStringValue();
057: int fingerprint = -1;
058: if (!format.equals("")) {
059: fingerprint = ((ExpressionContext) env).getFingerprint(
060: format, false);
061: if (fingerprint == -1) {
062: throw new StaticError("Output format '" + format
063: + "' has not been defined");
064: }
065: }
066: outputProperties = ((ExpressionContext) env)
067: .getXSLStylesheet().gatherOutputProperties(
068: fingerprint);
069: } else {
070: // we're not in XSLT: treat the second argument as the method property, default the rest
071: outputProperties = new Properties();
072: if (!(argument[1] instanceof StringValue)) {
073: throw new StaticError(
074: "Second argument of saxon:serialize must be known at compile time");
075: }
076: outputProperties.setProperty(OutputKeys.METHOD,
077: ((StringValue) argument[1]).getStringValue());
078: }
079: }
080:
081: /**
082: * Evaluate the function
083: */
084:
085: public Item evaluateItem(XPathContext c) throws XPathException {
086: NodeInfo node = (NodeInfo) argument[0].evaluateItem(c);
087: if (node == null) {
088: return StringValue.EMPTY_STRING;
089: }
090:
091: try {
092: StringWriter result = new StringWriter();
093: XPathContext c2 = c.newMinorContext();
094: c.setOriginatingConstructType(Location.SAXON_SERIALIZE);
095:
096: c2.changeOutputDestination(outputProperties,
097: new StreamResult(result), false,
098: Validation.PRESERVE, null);
099: SequenceReceiver out = c2.getReceiver();
100: out.open();
101: node.copy(out, NodeInfo.ALL_NAMESPACES, true, locationId);
102: out.close();
103: return new StringValue(result.toString());
104: } catch (XPathException err) {
105: throw new DynamicError(err);
106: }
107: }
108: }
109:
110: //
111: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
112: // you may not use this file except in compliance with the License. You may obtain a copy of the
113: // License at http://www.mozilla.org/MPL/
114: //
115: // Software distributed under the License is distributed on an "AS IS" basis,
116: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
117: // See the License for the specific language governing rights and limitations under the License.
118: //
119: // The Original Code is: all this file.
120: //
121: // The Initial Developer of the Original Code is Michael H. Kay.
122: //
123: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
124: //
125: // Contributor(s): none.
126: //
|