1 package net.sf.saxon.style; 2 import net.sf.saxon.expr.*; 3 import net.sf.saxon.instruct.Executable; 4 import net.sf.saxon.instruct.NumberInstruction; 5 import net.sf.saxon.instruct.ValueOf; 6 import net.sf.saxon.number.NumberFormatter; 7 import net.sf.saxon.number.Numberer; 8 import net.sf.saxon.number.Numberer_en; 9 import net.sf.saxon.om.AttributeCollection; 10 import net.sf.saxon.pattern.NodeKindTest; 11 import net.sf.saxon.pattern.Pattern; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.type.ItemType; 14 import net.sf.saxon.value.SequenceType; 15 import net.sf.saxon.value.StringValue; 16 17 20 21 public class XSLNumber extends StyleElement { 22 23 private static final int SINGLE = 0; 24 private static final int MULTI = 1; 25 private static final int ANY = 2; 26 private static final int SIMPLE = 3; 27 28 private int level; 29 private Pattern count = null; 30 private Pattern from = null; 31 private Expression select = null; 32 private Expression value = null; 33 private Expression format = null; 34 private Expression groupSize = null; 35 private Expression groupSeparator = null; 36 private Expression letterValue = null; 37 private Expression lang = null; 38 private Expression ordinal = null; 39 private NumberFormatter formatter = null; 40 private Numberer numberer = null; 41 private boolean hasVariablesInPatterns = false; 42 43 private static Numberer defaultNumberer = new Numberer_en(); 44 45 49 50 public boolean isInstruction() { 51 return true; 52 } 53 54 59 60 protected ItemType getReturnedItemType() { 61 return NodeKindTest.TEXT; 62 } 63 64 public void prepareAttributes() throws XPathException { 65 66 AttributeCollection atts = getAttributeList(); 67 68 String selectAtt = null; 69 String valueAtt = null; 70 String countAtt = null; 71 String fromAtt = null; 72 String levelAtt = null; 73 String formatAtt = null; 74 String gsizeAtt = null; 75 String gsepAtt = null; 76 String langAtt = null; 77 String letterValueAtt = null; 78 String ordinalAtt = null; 79 80 for (int a=0; a<atts.getLength(); a++) { 81 int nc = atts.getNameCode(a); 82 String f = getNamePool().getClarkName(nc); 83 if (f==StandardNames.SELECT) { 84 selectAtt = atts.getValue(a); 85 } else if (f==StandardNames.VALUE) { 86 valueAtt = atts.getValue(a); 87 } else if (f==StandardNames.COUNT) { 88 countAtt = atts.getValue(a); 89 } else if (f==StandardNames.FROM) { 90 fromAtt = atts.getValue(a); 91 } else if (f==StandardNames.LEVEL) { 92 levelAtt = atts.getValue(a).trim(); 93 } else if (f==StandardNames.FORMAT) { 94 formatAtt = atts.getValue(a); 95 } else if (f==StandardNames.LANG) { 96 langAtt = atts.getValue(a); 97 } else if (f==StandardNames.LETTER_VALUE) { 98 letterValueAtt = atts.getValue(a).trim(); 99 } else if (f==StandardNames.GROUPING_SIZE) { 100 gsizeAtt = atts.getValue(a).trim(); 101 } else if (f==StandardNames.GROUPING_SEPARATOR) { 102 gsepAtt = atts.getValue(a); 103 } else if (f==StandardNames.ORDINAL) { 104 ordinalAtt = atts.getValue(a); 105 } else { 106 checkUnknownAttribute(nc); 107 } 108 } 109 110 if (selectAtt != null) { 111 select = makeExpression(selectAtt); 112 } 113 114 if (valueAtt!=null) { 115 value = makeExpression(valueAtt); 116 if (selectAtt != null) { 117 compileError("The select attribute and value attribute must not both be present", "XTSE0975"); 118 } 119 if (countAtt != null) { 120 compileError("The count attribute and value attribute must not both be present", "XTSE0975"); 121 } 122 if (fromAtt != null) { 123 compileError("The from attribute and value attribute must not both be present", "XTSE0975"); 124 } 125 if (levelAtt != null) { 126 compileError("The level attribute and value attribute must not both be present", "XTSE0975"); 127 } 128 } 129 130 if (countAtt!=null) { 131 count = makePattern(countAtt); 132 if (countAtt.indexOf('$')>=0) { 135 hasVariablesInPatterns = true; 136 } 137 } 138 139 if (fromAtt!=null) { 140 from = makePattern(fromAtt); 141 if (fromAtt.indexOf('$')>=0) { 142 hasVariablesInPatterns = true; 143 } 144 } 145 146 if (levelAtt==null) { 147 level = SINGLE; 148 } else if (levelAtt.equals("single")) { 149 level = SINGLE; 150 } else if (levelAtt.equals("multiple")) { 151 level = MULTI; 152 } else if (levelAtt.equals("any")) { 153 level = ANY; 154 } else { 155 compileError("Invalid value for level attribute", "XTSE0020"); 156 } 157 158 if (level==SINGLE && from==null && count==null) { 159 level=SIMPLE; 160 } 161 162 if (formatAtt != null) { 163 format = makeAttributeValueTemplate(formatAtt); 164 if (format instanceof StringValue) { 165 formatter = new NumberFormatter(); 166 formatter.prepare(((StringValue)format).getStringValue()); 167 } 168 } else { 170 formatter = new NumberFormatter(); 171 formatter.prepare("1"); 172 } 173 174 if (gsepAtt!=null && gsizeAtt!=null) { 175 groupSize = makeAttributeValueTemplate(gsizeAtt); 177 groupSeparator = makeAttributeValueTemplate(gsepAtt); 178 } 179 180 if (langAtt==null) { 181 numberer = defaultNumberer; 182 } else { 183 lang = makeAttributeValueTemplate(langAtt); 184 if (lang instanceof StringValue) { 185 numberer = makeNumberer(((StringValue)lang).getStringValue()); 186 } } 188 189 if (letterValueAtt != null) { 190 letterValue = makeAttributeValueTemplate(letterValueAtt); 191 } 192 193 if (ordinalAtt != null) { 194 ordinal = makeAttributeValueTemplate(ordinalAtt); 195 } 196 197 } 198 199 public void validate() throws XPathException { 200 checkWithinTemplate(); 201 checkEmpty(); 202 203 select = typeCheck("select", select); 204 value = typeCheck("value", value); 205 format = typeCheck("format", format); 206 groupSize = typeCheck("group-size", groupSize); 207 groupSeparator = typeCheck("group-separator", groupSeparator); 208 letterValue = typeCheck("letter-value", letterValue); 209 ordinal = typeCheck("ordinal", ordinal); 210 lang = typeCheck("lang", lang); 211 from = typeCheck("from", from); 212 count = typeCheck("count", count); 213 214 if (select != null) { 215 try { 216 RoleLocator role = 217 new RoleLocator(RoleLocator.INSTRUCTION, "xsl:number/select", 0, null); 218 role.setSourceLocator(new ExpressionLocation(this)); 219 select = TypeChecker.staticTypeCheck(select, 220 SequenceType.SINGLE_NODE, 221 false, role, getStaticContext()); 222 } catch (XPathException err) { 223 compileError(err); 224 } 225 } 226 } 227 228 public Expression compile(Executable exec) throws XPathException { 229 NumberInstruction expr = new NumberInstruction ( select, 230 level, 231 count, 232 from, 233 value, 234 format, 235 groupSize, 236 groupSeparator, 237 letterValue, 238 ordinal, 239 lang, 240 formatter, 241 numberer, 242 hasVariablesInPatterns, 243 backwardsCompatibleModeIsEnabled()); 244 int loc = getStaticContext().getLocationMap().allocateLocationId(getSystemId(), getLineNumber()); 245 expr.setLocationId(loc); 246 ExpressionTool.makeParentReferences(expr); 247 ValueOf inst = new ValueOf(expr, false, false); 248 inst.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); 249 ExpressionTool.makeParentReferences(inst); 250 inst.setIsNumberingInstruction(); 251 return inst; 252 } 253 254 257 258 protected Numberer makeNumberer (String language) { 259 Numberer numberer; 260 if (language.equals("en")) { 261 numberer = defaultNumberer; 262 } else { 263 String langClassName = "net.sf.saxon.number.Numberer_"; 264 for (int i=0; i<language.length(); i++) { 265 if (Character.isLetter(language.charAt(i))) { 266 langClassName += language.charAt(i); 267 } 268 } 269 try { 270 numberer = (Numberer)(getConfiguration().getInstance(langClassName, null)); 271 } catch (Exception err) { 272 numberer = defaultNumberer; 273 } 274 } 275 276 return numberer; 277 } 278 } 279 280 | Popular Tags |