/** * The following function is called when it is found that the output is not a well-formed * document. Unless the ContentHandler accepts "balanced content", this is a fatal error. */ protected void notifyNotWellFormed() throws XPathException { DynamicError err = new DynamicError( "The result tree cannot be supplied to the ContentHandler because it is not well-formed XML"); err.setErrorCode(SaxonErrorCode.SXCH0002); throw err; }
/** * Evaluate the matches() function to give a Boolean value. * * @param c The dynamic evaluation context * @return the result as a BooleanValue, or null to indicate the empty sequence * @throws XPathException on an error */ public Item evaluateItem(XPathContext c) throws XPathException { AtomicValue sv0 = (AtomicValue) argument[0].evaluateItem(c); if (sv0 == null) { sv0 = StringValue.EMPTY_STRING; } ; RegularExpression re = regexp; if (re == null) { AtomicValue pat = (AtomicValue) argument[1].evaluateItem(c); if (pat == null) return null; CharSequence flags; if (argument.length == 2) { flags = ""; } else { AtomicValue sv2 = (AtomicValue) argument[2].evaluateItem(c); if (sv2 == null) return null; flags = sv2.getStringValueCS(); } try { final Platform platform = c.getConfiguration().getPlatform(); re = platform.compileRegularExpression(pat.getStringValueCS(), true, flags); } catch (XPathException err) { DynamicError de = new DynamicError(err); de.setErrorCode("FORX0002"); de.setXPathContext(c); throw de; } } return BooleanValue.get(re.containsMatch(sv0.getStringValueCS())); }
/** * Set the Java flags from the supplied XPath flags. * * @param inFlags the flags as a string, e.g. "im" * @return the flags as a bit-significant integer * @throws DynamicError if the supplied value is invalid */ public static int setFlags(CharSequence inFlags) throws DynamicError { int flags = Pattern.UNIX_LINES; for (int i = 0; i < inFlags.length(); i++) { char c = inFlags.charAt(i); switch (c) { case 'm': flags |= Pattern.MULTILINE; break; case 'i': flags |= Pattern.CASE_INSENSITIVE; flags |= Pattern.UNICODE_CASE; break; case 's': flags |= Pattern.DOTALL; break; case 'x': flags |= Pattern.COMMENTS; // note, this enables comments as well as whitespace break; default: DynamicError err = new DynamicError("Invalid character '" + c + "' in regular expression flags"); err.setErrorCode("FORX0001"); throw err; } } return flags; }
/** Handle a SAXException thrown by the ContentHandler */ public void handleSAXException(SAXException err) throws XPathException { Exception nested = err.getException(); if (nested instanceof XPathException) { throw (XPathException) nested; } else if (nested instanceof SchemaException) { throw new DynamicError(nested); } else { DynamicError de = new DynamicError(err); de.setErrorCode(SaxonErrorCode.SXCH0003); throw de; } }
/** * Type-check the expression. This also calls preEvaluate() to evaluate the function if all the * arguments are constant; functions that do not require this behavior can override the * preEvaluate method. */ public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { try { return super.typeCheck(env, contextItemType); } catch (XPathException err) { if ("XPDY0002".equals(err.getErrorCodeLocalPart())) { DynamicError e = new DynamicError("Cannot call the key() function when there is no context node"); e.setErrorCode("XTDE1270"); throw e; } throw err; } }
/** Evaluate in a general context */ public Item evaluateItem(XPathContext c) throws XPathException { StringValue sv = (StringValue) argument[0].evaluateItem(c); if (sv == null) { return StringValue.EMPTY_STRING; } byte fb = Normalizer.C; if (argument.length == 2) { String form = argument[1].evaluateAsString(c).trim(); if (form.equalsIgnoreCase("NFC")) { fb = Normalizer.C; } else if (form.equalsIgnoreCase("NFD")) { fb = Normalizer.D; } else if (form.equalsIgnoreCase("NFKC")) { fb = Normalizer.KC; } else if (form.equalsIgnoreCase("NFKD")) { fb = Normalizer.KD; } else if (form.equalsIgnoreCase("")) { return sv; } else { String msg = "Normalization form " + form + " is not supported"; DynamicError err = new DynamicError(msg); err.setErrorCode("FOCH0003"); err.setXPathContext(c); err.setLocator(this); throw err; } } // fast path for ASCII strings: normalization is a no-op boolean allASCII = true; CharSequence chars = sv.getStringValueCS(); if (chars instanceof CompressedWhitespace) { return sv; } for (int i = chars.length() - 1; i >= 0; i--) { if (chars.charAt(i) > 127) { allASCII = false; break; } } if (allASCII) { return sv; } Normalizer norm = new Normalizer(fb); CharSequence result = norm.normalize(sv.getStringValueCS()); return StringValue.makeStringValue(result); }
/** * Process this instruction * * @param context the dynamic context of the transformation * @return a TailCall to be executed by the caller, always null for this instruction */ public TailCall processLeavingTail(XPathContext context) throws XPathException { Controller controller = context.getController(); SequenceReceiver out = context.getReceiver(); int opt = options; int ann = annotation; // we may need to change the namespace prefix if the one we chose is // already in use with a different namespace URI: this is done behind the scenes // by the Outputter CharSequence value = expandChildren(context); if (schemaType != null) { // test whether the value actually conforms to the given type XPathException err = schemaType.validateContent( value, DummyNamespaceResolver.getInstance(), context.getConfiguration().getNameChecker()); if (err != null) { ValidationException verr = new ValidationException( "Attribute value " + Err.wrap(value, Err.VALUE) + " does not the match the required type " + schemaType.getDescription() + ". " + err.getMessage()); verr.setErrorCode("XTTE1540"); verr.setLocator(this); throw verr; } } else if (validationAction == Validation.STRICT || validationAction == Validation.LAX) { try { ann = controller.getConfiguration().validateAttribute(nameCode, value, validationAction); } catch (ValidationException e) { DynamicError err = DynamicError.makeDynamicError(e); String errorCode = e.getErrorCodeLocalPart(); if (errorCode == null) { errorCode = (validationAction == Validation.STRICT ? "XTTE1510" : "XTTE1515"); } err.setErrorCode(errorCode); err.setXPathContext(context); err.setLocator(this); err.setIsTypeError(true); throw err; } } try { out.attribute(nameCode, ann, value, locationId, opt); } catch (XPathException err) { throw dynamicError(this, err, context); } return null; }
public Item evaluateItem(XPathContext context) throws XPathException { Orphan o = (Orphan) super.evaluateItem(context); if (schemaType != null) { XPathException err = schemaType.validateContent( o.getStringValueCS(), DummyNamespaceResolver.getInstance(), context.getConfiguration().getNameChecker()); if (err != null) { throw new ValidationException( "Attribute value " + Err.wrap(o.getStringValueCS(), Err.VALUE) + " does not the match the required type " + schemaType.getDescription() + ". " + err.getMessage()); } o.setTypeAnnotation(schemaType.getFingerprint()); if (schemaType.isNamespaceSensitive()) { throw new DynamicError( "Cannot validate a parentless attribute whose content is namespace-sensitive"); } } else if (validationAction == Validation.STRICT || validationAction == Validation.LAX) { try { int ann = context .getController() .getConfiguration() .validateAttribute(nameCode, o.getStringValueCS(), validationAction); o.setTypeAnnotation(ann); } catch (ValidationException e) { DynamicError err = DynamicError.makeDynamicError(e); err.setErrorCode(e.getErrorCodeLocalPart()); err.setXPathContext(context); err.setLocator(this); err.setIsTypeError(true); throw err; } } return o; }
/** * 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()); }
public void process(XPathContext context) throws XPathException { // Prepare the SQL statement (only do this once) Controller controller = context.getController(); Item conn = arguments[CONNECTION].evaluateItem(context); if (!(conn instanceof ObjectValue && ((ObjectValue) conn).getObject() instanceof Connection)) { DynamicError de = new DynamicError("Value of connection expression is not a JDBC Connection"); de.setXPathContext(context); throw de; } Connection connection = (Connection) ((ObjectValue) conn).getObject(); String dbCol = arguments[COLUMN].evaluateAsString(context); String dbTab = arguments[TABLE].evaluateAsString(context); String dbWhere = arguments[WHERE].evaluateAsString(context); NamePool pool = controller.getNamePool(); int rowCode = pool.allocate("", "", rowTag); int colCode = pool.allocate("", "", colTag); PreparedStatement ps = null; ResultSet rs = null; DynamicError de = null; try { StringBuffer statement = new StringBuffer(); statement.append("SELECT " + dbCol + " FROM " + dbTab); if (dbWhere != "") { statement.append(" WHERE " + dbWhere); } // System.err.println("-> SQL: " + statement.toString()); // -- Prepare the SQL statement ps = connection.prepareStatement(statement.toString()); controller.setUserData(this, "sql:statement", ps); // -- Execute Statement rs = ps.executeQuery(); // -- Print out Result Receiver out = context.getReceiver(); String result = ""; int icol = rs.getMetaData().getColumnCount(); while (rs.next()) { // next row // System.out.print("<- SQL : "+ rowStart); out.startElement(rowCode, StandardNames.XDT_UNTYPED, locationId, 0); for (int col = 1; col <= icol; col++) { // next column // Read result from RS only once, because // of JDBC-Specifications result = rs.getString(col); out.startElement(colCode, StandardNames.XDT_UNTYPED, locationId, 0); if (result != null) { out.characters(result, locationId, options); } out.endElement(); } // System.out.println(rowEnd); out.endElement(); } // rs.close(); if (!connection.getAutoCommit()) { connection.commit(); } } catch (SQLException ex) { de = new DynamicError("(SQL) " + ex.getMessage()); de.setXPathContext(context); throw de; } finally { boolean wasDEThrown = (de != null); if (rs != null) { try { rs.close(); } catch (SQLException ex) { de = new DynamicError("(SQL) " + ex.getMessage()); de.setXPathContext(context); } } if (ps != null) { try { ps.close(); } catch (SQLException ex) { de = new DynamicError("(SQL) " + ex.getMessage()); de.setXPathContext(context); } } if (!wasDEThrown && de != null) { throw de; // test so we don't lose the real exception } } }
/** Allocate a Comparator to perform the comparisons described by this sort key component */ public Comparator makeComparator(XPathContext context) throws XPathException { String orderX = order.evaluateAsString(context); final Configuration config = context.getConfiguration(); final TypeHierarchy th = config.getTypeHierarchy(); Comparator comp; if (collation != null) { comp = collation; } else if (collationName != null) { String cname = collationName.evaluateAsString(context); URI collationURI; try { collationURI = new URI(cname); if (!collationURI.isAbsolute()) { if (baseURI == null) { throw new DynamicError("Collation URI is relative, and base URI is unknown"); } else { URI base = new URI(baseURI); collationURI = base.resolve(collationURI); } } } catch (URISyntaxException err) { throw new DynamicError("Collation name " + cname + " is not a valid URI: " + err); } try { comp = context.getCollation(collationURI.toString()); } catch (XPathException e) { if ("FOCH0002".equals(e.getErrorCodeLocalPart())) { e.setErrorCode("XTDE1035"); } throw e; } } else { String caseOrderX = caseOrder.evaluateAsString(context); String languageX = language.evaluateAsString(context); Properties props = new Properties(); if (!languageX.equals("")) { props.setProperty("lang", languageX); } if (!caseOrderX.equals("#default")) { props.setProperty("case-order", caseOrderX); } comp = config.getPlatform().makeCollation(config, props); } if (dataTypeExpression == null) { int type = sortKey.getItemType(th).getAtomizedItemType().getPrimitiveType(); comp = AtomicSortComparer.makeSortComparer(comp, type, context); if (!emptyLeast) { comp = new EmptyGreatestComparer((AtomicComparer) comp); } } else { String dataType = dataTypeExpression.evaluateAsString(context); if (dataType.equals("text")) { comp = new TextComparer(comp); } else if (dataType.equals("number")) { comp = NumericComparer.getInstance(); } else { DynamicError err = new DynamicError("data-type on xsl:sort must be 'text' or 'number'"); err.setErrorCode("XTDE0030"); throw err; } } if (stable != null) { StringValue stableVal = (StringValue) stable.evaluateItem(context); String s = stableVal.getStringValue().trim(); if (s.equals("yes") || s.equals("no")) { // no action } else { DynamicError err = new DynamicError("Value of 'stable' on xsl:sort must be 'yes' or 'no'"); err.setErrorCode("XTDE0030"); throw err; } } if (orderX.equals("ascending")) { return comp; } else if (orderX.equals("descending")) { return new DescendingComparer(comp); } else { DynamicError err1 = new DynamicError("order must be 'ascending' or 'descending'"); err1.setErrorCode("XTDE0030"); throw err1; } }