001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.charcode.UnicodeCharacterSet;
004: import net.sf.saxon.expr.XPathContext;
005: import net.sf.saxon.om.Item;
006: import net.sf.saxon.om.FastStringBuffer;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.value.AtomicValue;
009: import net.sf.saxon.value.BooleanValue;
010: import net.sf.saxon.value.StringValue;
011: import net.sf.saxon.event.HTMLURIEscaper;
012:
013: /**
014: * This class supports the old function escape-uri() and the new replacement functions
015: * encode-for-uri() and iri-to-uri()
016: */
017:
018: public class EscapeURI extends SystemFunction {
019:
020: public static final int ESCAPE = 0; // obsolete escape-uri() function
021: public static final int ENCODE_FOR_URI = 1;
022: public static final int IRI_TO_URI = 2;
023: public static final int HTML_URI = 3;
024:
025: /**
026: * Evaluate the function
027: */
028:
029: public Item evaluateItem(XPathContext c) throws XPathException {
030: Item item = argument[0].evaluateItem(c);
031: if (item == null) {
032: return StringValue.EMPTY_STRING;
033: }
034: CharSequence s = item.getStringValueCS();
035: boolean escapeReserved = false;
036: switch (operation) {
037: case ESCAPE:
038: AtomicValue av2 = (AtomicValue) argument[1].evaluateItem(c);
039: escapeReserved = ((BooleanValue) av2.getPrimitiveValue())
040: .getBooleanValue();
041: break;
042: case ENCODE_FOR_URI:
043: escapeReserved = true;
044: break;
045: case IRI_TO_URI:
046: escapeReserved = false;
047: break;
048: case HTML_URI:
049: return StringValue.makeStringValue(HTMLURIEscaper
050: .escapeURL(s));
051: }
052: return StringValue.makeStringValue(escape(s, escapeReserved));
053: }
054:
055: public static CharSequence escape(CharSequence s,
056: boolean escapeReserved) {
057: FastStringBuffer sb = new FastStringBuffer(s.length());
058: for (int i = 0; i < s.length(); i++) {
059: char c = s.charAt(i);
060: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
061: || (c >= '0' && c <= '9')) {
062: sb.append(c);
063: } else if (c <= 0x20 || c >= 0x7f) {
064: escapeChar(c, ((i + 1) < s.length() ? s.charAt(i + 1)
065: : ' '), sb);
066: } else if (escapeReserved) {
067: if ("#-_.!~*'()".indexOf(c) >= 0) {
068: sb.append(c);
069: } else {
070: escapeChar(c, ' ', sb);
071: }
072: } else {
073: if ("#-_.!~*'();/?:@&=+$,[]%".indexOf(c) >= 0) {
074: sb.append(c);
075: } else {
076: escapeChar(c, ' ', sb);
077: }
078: }
079: }
080: return sb;
081: }
082:
083: private static final String hex = "0123456789ABCDEF";
084:
085: private static void escapeChar(char c, char c2, FastStringBuffer sb) {
086: byte[] array = new byte[4];
087: int used = UnicodeCharacterSet.getUTF8Encoding(c, c2, array);
088: for (int b = 0; b < used; b++) {
089: //int v = (array[b]>=0 ? array[b] : 256 + array[b]);
090: int v = (int) array[b] & 0xff;
091: sb.append('%');
092: sb.append(hex.charAt(v / 16));
093: sb.append(hex.charAt(v % 16));
094: }
095: }
096: }
097:
098: //
099: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
100: // you may not use this file except in compliance with the License. You may obtain a copy of the
101: // License at http://www.mozilla.org/MPL/
102: //
103: // Software distributed under the License is distributed on an "AS IS" basis,
104: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
105: // See the License for the specific language governing rights and limitations under the License.
106: //
107: // The Original Code is: all this file.
108: //
109: // The Initial Developer of the Original Code is Michael H. Kay
110: //
111: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
112: //
113: // Contributor(s): none.
114: //
|