KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > style > LiteralResultElement


1 package net.sf.saxon.style;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.PreparedStylesheet;
4 import net.sf.saxon.expr.Expression;
5 import net.sf.saxon.expr.ExpressionTool;
6 import net.sf.saxon.expr.ComputedExpression;
7 import net.sf.saxon.instruct.*;
8 import net.sf.saxon.om.*;
9 import net.sf.saxon.trace.Location;
10 import net.sf.saxon.trans.SaxonErrorCode;
11 import net.sf.saxon.trans.StaticError;
12 import net.sf.saxon.trans.XPathException;
13 import net.sf.saxon.tree.DocumentImpl;
14 import net.sf.saxon.tree.TreeBuilder;
15 import net.sf.saxon.type.SchemaType;
16 import net.sf.saxon.value.EmptySequence;
17
18 import javax.xml.transform.TransformerException JavaDoc;
19
20
21 /**
22 * This class represents a literal result element in the style sheet
23 * (typically an HTML element to be output). <br>
24 * It is also used to represent unknown top-level elements, which are ignored.
25 */

26
27 public class LiteralResultElement extends StyleElement {
28
29     private int resultNameCode;
30     private int[] attributeNames;
31     private Expression[] attributeValues;
32 // private boolean[] attributeChecked;
33
private int numberOfAttributes;
34     private boolean toplevel;
35     private int[] namespaceCodes;
36     private AttributeSet[] attributeSets;
37     private SchemaType schemaType = null;
38     private int validation = Validation.STRIP;
39     private boolean inheritNamespaces = true;
40
41     /**
42     * Determine whether this type of element is allowed to contain a template-body
43     * @return true: yes, it may contain a template-body
44     */

45
46     public boolean mayContainSequenceConstructor() {
47         return true;
48     }
49
50     /**
51      * Specify that this is an instruction
52      */

53
54     public boolean isInstruction() {
55         return true;
56     }
57
58     /**
59     * Process the attribute list
60     */

61
62     public void prepareAttributes() throws XPathException {
63
64         // Process the values of all attributes. At this stage we deal with attribute
65
// values (especially AVTs), but we do not apply namespace aliasing to the
66
// attribute names.
67

68         int num = attributeList.getLength();
69
70         if (num == 0) {
71             numberOfAttributes = 0;
72         } else {
73             NamePool namePool = getNamePool();
74             attributeNames = new int[num];
75             attributeValues = new Expression[num];
76 // attributeChecked = new boolean[num];
77
numberOfAttributes = 0;
78
79             for (int i=0; i<num; i++) {
80
81                 int anameCode = attributeList.getNameCode(i);
82                 short attURIcode = namePool.getURICode(anameCode);
83
84                 if (attURIcode==NamespaceConstant.XSLT_CODE) {
85                     int fp = anameCode & 0xfffff;
86
87                     if (fp == StandardNames.XSL_USE_ATTRIBUTE_SETS) {
88                         // deal with this later
89
} else if (fp == StandardNames.XSL_DEFAULT_COLLATION) {
90                         // already dealt with
91
} else if (fp == StandardNames.XSL_EXTENSION_ELEMENT_PREFIXES) {
92                         // already dealt with
93
} else if (fp == StandardNames.XSL_EXCLUDE_RESULT_PREFIXES) {
94                         // already dealt with
95
} else if (fp == StandardNames.XSL_VERSION) {
96                         // already dealt with
97
} else if (fp == StandardNames.XSL_XPATH_DEFAULT_NAMESPACE) {
98                         // already dealt with
99
} else if (fp == StandardNames.XSL_TYPE) {
100                         // deal with this later
101
} else if (fp == StandardNames.XSL_USE_WHEN) {
102                         // already dealt with
103
} else if (fp == StandardNames.XSL_VALIDATION) {
104                         // deal with this later
105
} else if (fp == StandardNames.XSL_INHERIT_NAMESPACES) {
106                         String JavaDoc inheritAtt = attributeList.getValue(i);
107                         if (inheritAtt.equals("yes")) {
108                             inheritNamespaces = true;
109                         } else if (inheritAtt.equals("no")) {
110                             inheritNamespaces = false;
111                         } else {
112                             compileError("The xsl:inherit-namespaces attribute has permitted values (yes, no)", "XTSE0020");
113                         }
114                     } else {
115                         compileError("Unknown XSL attribute " + namePool.getDisplayName(anameCode), "XTSE0010");
116                     }
117                 } else {
118                     attributeNames[numberOfAttributes] = anameCode;
119                     Expression exp = makeAttributeValueTemplate(attributeList.getValue(i));
120                     attributeValues[numberOfAttributes] = exp;
121
122                     // if we can be sure the attribute value contains no special XML/HTML characters,
123
// we can save the trouble of checking it each time it is output.
124
// Note that the check includes characters that need to be escaped in a URL if the
125
// output method turns out to be HTML (we don't know the method at compile time).
126

127 // attributeChecked[numberOfAttributes] = false;
128
// boolean special = false;
129
// if (exp instanceof StringValue) {
130
// CharSequence val = ((StringValue)exp).getStringValueCS();
131
// for (int k=0; k<val.length(); k++) {
132
// char c = val.charAt(k);
133
// if ((int)c<33 || (int)c>126 ||
134
// c=='<' || c=='>' || c=='&' || c=='\"') {
135
// special = true;
136
// break;
137
// }
138
// }
139
// attributeChecked[numberOfAttributes] = !special;
140
// }
141
numberOfAttributes++;
142                 }
143             }
144
145             // now shorten the arrays if necessary. This is necessary if there are [xsl:]-prefixed
146
// attributes that weren't copied into the arrays.
147

148             if (numberOfAttributes < attributeNames.length) {
149
150                 int[] attributeNames2 = new int[numberOfAttributes];
151                 System.arraycopy(attributeNames, 0, attributeNames2, 0, numberOfAttributes);
152                 attributeNames = attributeNames2;
153
154                 Expression[] attributeValues2 = new Expression[numberOfAttributes];
155                 System.arraycopy(attributeValues, 0, attributeValues2, 0, numberOfAttributes);
156                 attributeValues = attributeValues2;
157
158 // boolean[] attributeChecked2 = new boolean[numberOfAttributes];
159
// System.arraycopy(attributeChecked, 0, attributeChecked2, 0, numberOfAttributes);
160
// attributeChecked = attributeChecked2;
161
}
162         }
163     }
164
165     /**
166     * Validate that this node is OK
167     */

168
169     public void validate() throws XPathException {
170
171         toplevel = (getParent() instanceof XSLStylesheet);
172
173         resultNameCode = getNameCode();
174
175         NamePool namePool = getNamePool();
176         short elementURICode = namePool.getURICode(resultNameCode);
177
178         if (toplevel) {
179             // A top-level element can never be a "real" literal result element,
180
// but this class gets used for unknown elements found at the top level
181

182             if (elementURICode == 0) {
183                 compileError("Top level elements must have a non-null namespace URI", "XTSE0010");
184             }
185         } else {
186
187             // Build the list of output namespace nodes
188

189             // Up to 5.3.1 we listed the namespace nodes associated with this element that were not also
190
// associated with an ancestor literal result element (because those will already
191
// have been output). Unfortunately this isn't true if the namespace was present on an outer
192
// LRE, and was excluded at that level using exclude-result-prefixes, and is now used in an
193
// inner element: bug 5.3.1/006
194

195             // We now use a different optimisation: if
196
// (a) this LRE has a parent that is also an LRE, and
197
// (b) this LRE has no namespace declarations of its own, and
198
// (c) this element name is in the same namespace as its parent, and
199
// (d) the parent doesn't specify xsl:inherit-namespaces="no"
200
// (e) there are no attributes in a non-null namespace,
201
// then we don't need to output any namespace declarations to the result.
202

203             boolean optimizeNS = false;
204             NodeInfo parent = getParent();
205             if ((parent instanceof LiteralResultElement) &&
206                     ((LiteralResultElement)parent).inheritNamespaces &&
207                     (namespaceList==null || namespaceList.length==0) &&
208                     ( elementURICode == namePool.getURICode(getParent().getFingerprint()))) {
209                 optimizeNS = true;
210             }
211             if (optimizeNS) {
212                 for (int a=0; a<attributeList.getLength(); a++ ) {
213                     if (((attributeList.getNameCode(a)>>20)&0xff) != 0) { // prefix != ""
214
optimizeNS = false;
215                         break;
216                     }
217                 }
218             }
219
220             if (optimizeNS) {
221                 namespaceCodes = NodeInfo.EMPTY_NAMESPACE_LIST;
222             } else {
223                 namespaceCodes = getInScopeNamespaceCodes();
224             }
225
226             // apply any aliases required to create the list of output namespaces
227

228             XSLStylesheet sheet = getPrincipalStylesheet();
229
230             if (sheet.hasNamespaceAliases()) {
231                 for (int i=0; i<namespaceCodes.length; i++) {
232                     // System.err.println("Examining namespace " + namespaceCodes[i]);
233
short scode = (short)(namespaceCodes[i]&0xffff);
234                     int ncode = sheet.getNamespaceAlias(scode);
235                     if (ncode != -1 && (ncode & 0xffff) != scode) {
236                         // apply the namespace alias. Change in 7.3: use the prefix associated
237
// with the new namespace, not the old prefix.
238
namespaceCodes[i] = ncode;
239                     }
240                 }
241
242                 // determine if there is an alias for the namespace of the element name
243

244                 int ercode = sheet.getNamespaceAlias(elementURICode);
245                 if ((ercode & 0xffff) != elementURICode) {
246                     resultNameCode = namePool.allocate(namePool.getPrefixFromNamespaceCode(ercode),
247                                                        namePool.getURIFromNamespaceCode(ercode),
248                                                        getLocalPart());
249                 }
250             }
251
252             // deal with special attributes
253

254             String JavaDoc useAttSets = getAttributeValue(StandardNames.XSL_USE_ATTRIBUTE_SETS);
255             if (useAttSets != null) {
256                 attributeSets = getAttributeSets(useAttSets, null);
257             }
258
259             String JavaDoc type = getAttributeValue(StandardNames.XSL_TYPE);
260             if (type != null) {
261                 if (!getConfiguration().isSchemaAware(Configuration.XSLT)) {
262                     compileError("The xsl:type attribute is available only with a schema-aware XSLT processor", "XTSE1660");
263                 }
264                 schemaType = getSchemaType(type);
265             }
266
267             String JavaDoc validate = getAttributeValue(StandardNames.XSL_VALIDATION);
268             if (validate != null) {
269                 validation = Validation.getCode(validate);
270                 if (validation != Validation.STRIP && !getConfiguration().isSchemaAware(Configuration.XSLT)) {
271                     compileError("To perform validation, a schema-aware XSLT processor is needed", "XTSE1660");
272                 }
273                 if (validation == Validation.INVALID) {
274                     compileError("Invalid value for xsl:validation. " +
275                                  "Permitted values are (strict, lax, preserve, strip)", "XTSE0020");
276                 }
277             } else {
278                 validation = getContainingStylesheet().getDefaultValidation();
279             }
280
281             // establish the names to be used for all the output attributes;
282
// also type-check the AVT expressions
283

284             short attributeURIs[] = new short[numberOfAttributes];
285             if (numberOfAttributes > 0) {
286
287                 for (int i=0; i<numberOfAttributes; i++) {
288
289                     int anameCode = attributeNames[i];
290                     int alias = anameCode;
291                     short attURIcode = namePool.getURICode(anameCode);
292
293                     if (attURIcode!=0) { // attribute has a namespace prefix
294
int newNSCode = sheet.getNamespaceAlias(attURIcode);
295                         if ((newNSCode & 0xffff) != attURIcode) {
296                             attURIcode = (short)(newNSCode & 0xffff);
297                             alias = namePool.allocate( namePool.getPrefixFromNamespaceCode(newNSCode),
298                                                        namePool.getURIFromNamespaceCode(newNSCode),
299                                                        attributeList.getLocalName(i));
300                         }
301                     }
302
303                     //attributeNames[i] = translate(alias);
304
attributeNames[i] = alias;
305                     attributeURIs[i] = attURIcode;
306                     attributeValues[i] = typeCheck(namePool.getDisplayName(alias), attributeValues[i]);
307                 }
308             }
309
310             // remove any namespaces that are on the exclude-result-prefixes list, unless it is
311
// the namespace of the element or an attribute
312

313             int numberExcluded = 0;
314             for (int n=0; n<namespaceCodes.length; n++) {
315                 short uricode = (short)(namespaceCodes[n] & 0xffff);
316                 if (isExcludedNamespace(uricode) && !sheet.isAliasResultNamespace(uricode)) {
317                     // exclude it from the output namespace list
318
namespaceCodes[n] = -1;
319                     numberExcluded++;
320                 }
321             }
322
323             // Now translate the list of namespace codes to use the target namepool,
324
// getting rid of the -1 entries while we go.
325

326 // int count = namespaceCodes.length - numberExcluded;
327
// NamePool oldPool = getNamePool();
328
// NamePool newPool = getTargetNamePool();
329
// // these must now be the same name pool?
330
// int[] newNamespaceCodes = new int[count];
331
// count = 0;
332
// for (int i=0; i<namespaceCodes.length; i++) {
333
// if (namespaceCodes[i] != -1) {
334
// String prefix = oldPool.getPrefixFromNamespaceCode(namespaceCodes[i]);
335
// String uri = oldPool.getURIFromNamespaceCode(namespaceCodes[i]);
336
// newNamespaceCodes[count++] = newPool.allocateNamespaceCode(prefix, uri);
337
// }
338
// }
339
// namespaceCodes = newNamespaceCodes;
340

341             int count = namespaceCodes.length - numberExcluded;
342             int[] newNamespaceCodes = new int[count];
343             count = 0;
344             for (int i=0; i<namespaceCodes.length; i++) {
345                 if (namespaceCodes[i] != -1) {
346                     newNamespaceCodes[count++] = namespaceCodes[i];
347                 }
348             }
349             namespaceCodes = newNamespaceCodes;
350         }
351     }
352
353     /**
354     * Validate the children of this node, recursively. Overridden for top-level
355     * data elements.
356     */

357
358     protected void validateChildren() throws XPathException {
359         if (!toplevel) {
360             super.validateChildren();
361         }
362     }
363
364     /**
365     * Translate a namecode in the stylesheet namepool to a namecode in the target namepool
366     */

367
368 // private int translate(int oldNameCode) {
369
// NamePool oldPool = getNamePool();
370
// NamePool newPool = getTargetNamePool();
371
// String prefix = oldPool.getPrefix(oldNameCode);
372
// String uri = oldPool.getURI(oldNameCode);
373
// String localName = oldPool.getLocalName(oldNameCode);
374
// return newPool.allocate(prefix, uri, localName);
375
// }
376

377     /**
378     * Process the literal result element by copying it to the result tree
379     */

380
381     public Expression compile(Executable exec) throws XPathException {
382         // top level elements in the stylesheet are ignored
383
if (toplevel) return null;
384
385         FixedElement inst = new FixedElement(
386                         resultNameCode,
387                         namespaceCodes,
388                         inheritNamespaces,
389                         schemaType,
390                         validation);
391
392         Expression content = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true);
393         if (content instanceof ComputedExpression) {
394             ((ComputedExpression)content).setParentExpression(inst);
395         }
396
397         if (numberOfAttributes > 0) {
398             for (int i=attributeNames.length - 1; i>=0; i--) {
399                 FixedAttribute att = new FixedAttribute(
400                         attributeNames[i],
401                         Validation.STRIP,
402                         null,
403                         StandardNames.XDT_UNTYPED_ATOMIC);
404                 try {
405                     att.setSelect(attributeValues[i]);
406                 } catch (XPathException err) {
407                     compileError(err);
408                 }
409                 att.setLocationId(allocateLocationId(getSystemId(), getLineNumber()));
410                 att.setParentExpression(inst);
411                 ExpressionTool.makeParentReferences(att);
412 // if (attributeChecked[i]) {
413
// att.setNoSpecialChars();
414
// }
415
if (content == null) {
416                     content = att;
417                 } else {
418                     content = Block.makeBlock(att, content);
419                 }
420             }
421         }
422
423         if (attributeSets != null) {
424             UseAttributeSets use = new UseAttributeSets(attributeSets);
425             if (content == null) {
426                 content = use;
427             } else {
428                 content = Block.makeBlock(use, content);
429             }
430         }
431
432         if (content == null) {
433             content = EmptySequence.getInstance();
434         }
435         inst.setContentExpression(content);
436
437         ExpressionTool.makeParentReferences(inst);
438         return inst;
439     }
440
441     /**
442     * Make a top-level literal result element into a stylesheet. This implements
443     * the "Literal Result Element As Stylesheet" facility.
444     */

445
446     public DocumentImpl makeStylesheet(PreparedStylesheet pss,
447                                        StyleNodeFactory nodeFactory)
448             throws XPathException {
449
450         // the implementation grafts the LRE node onto a containing xsl:template and
451
// xsl:stylesheet
452

453         NamePool pool = getNamePool();
454         String JavaDoc xslPrefix = getPrefixForURI(NamespaceConstant.XSLT);
455         if (xslPrefix==null) {
456             String JavaDoc message;
457             if (getLocalPart().equals("stylesheet") || getLocalPart().equals("transform")) {
458                 if (getPrefixForURI(NamespaceConstant.MICROSOFT_XSL)!=null) {
459                     message = "Saxon is not able to process Microsoft's WD-xsl dialect";
460                 } else {
461                     message = "Namespace for stylesheet element should be " + NamespaceConstant.XSLT;
462                 }
463             } else {
464                 message = "The supplied file does not appear to be a stylesheet";
465             }
466             StaticError err = new StaticError (message);
467             err.setLocator(this);
468             err.setErrorCode(SaxonErrorCode.SXIN0004);
469             try {
470                 pss.reportError(err);
471             } catch (TransformerException JavaDoc err2) {}
472             throw err;
473
474         }
475
476         // check there is an xsl:version attribute (it's mandatory), and copy
477
// it to the new xsl:stylesheet element
478

479         String JavaDoc version = getAttributeValue(StandardNames.XSL_VERSION);
480         if (version==null) {
481             StaticError err = new StaticError (
482                 "Simplified stylesheet: xsl:version attribute is missing");
483             err.setErrorCode("XTSE0150");
484             err.setLocator(this);
485             try {
486                 pss.reportError(err);
487             } catch(TransformerException JavaDoc err2) {}
488             throw err;
489         }
490
491         try {
492             TreeBuilder builder = new TreeBuilder();
493             builder.setPipelineConfiguration(pss.getConfiguration().makePipelineConfiguration());
494             builder.setNodeFactory(nodeFactory);
495             builder.setSystemId(this.getSystemId());
496
497             builder.open();
498             builder.startDocument(0);
499
500             int st = StandardNames.XSL_STYLESHEET;
501             builder.startElement(st, StandardNames.XDT_UNTYPED, 0, 0);
502             builder.namespace(NamespaceConstant.XSLT_CODE, 0);
503             builder.attribute(pool.allocate("", "", "version"), StandardNames.XDT_UNTYPED_ATOMIC, version, 0, 0);
504             builder.startContent();
505
506             int te = StandardNames.XSL_TEMPLATE;
507             builder.startElement(te, StandardNames.XDT_UNTYPED, 0, 0);
508             builder.attribute(pool.allocate("", "", "match"), StandardNames.XDT_UNTYPED_ATOMIC, "/", 0, 0);
509             builder.startContent();
510
511             builder.graftElement(this);
512
513             builder.endElement();
514             builder.endElement();
515             builder.endDocument();
516             builder.close();
517
518             return (DocumentImpl)builder.getCurrentRoot();
519         } catch (XPathException err) {
520             //TransformerConfigurationException e = new TransformerConfigurationException(err);
521
err.setLocator(this);
522             throw err;
523         }
524
525     }
526
527     /**
528      * Get the type of construct. This will be a constant in
529      * class {@link net.sf.saxon.trace.Location}. This method is part of the
530      * {@link net.sf.saxon.trace.InstructionInfo} interface
531      */

532
533     public int getConstructType() {
534         return Location.LITERAL_RESULT_ELEMENT;
535     }
536
537     /**
538      * Get a name identifying the object of the expression, for example a function name, template name,
539      * variable name, key name, element name, etc. This is used only where the name is known statically.
540      * If there is no name, the value will be -1.
541      */

542
543     public int getObjectNameCode() {
544         return resultNameCode;
545     }
546
547     /**
548      * Get the value of a particular property of the instruction. This is part of the
549      * {@link net.sf.saxon.trace.InstructionInfo} interface for run-time tracing and debugging. The properties
550      * available include all the attributes of the source instruction (named by the attribute name):
551      * these are all provided as string values.
552      * @param name The name of the required property
553      * @return The value of the requested property, or null if the property is not available
554      */

555
556     public Object JavaDoc getProperty(String JavaDoc name) {
557         if (name.equals("name")) {
558             return getDisplayName();
559         }
560         return null;
561     }
562
563 }
564 //
565
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
566
// you may not use this file except in compliance with the License. You may obtain a copy of the
567
// License at http://www.mozilla.org/MPL/
568
//
569
// Software distributed under the License is distributed on an "AS IS" basis,
570
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
571
// See the License for the specific language governing rights and limitations under the License.
572
//
573
// The Original Code is: all this file.
574
//
575
// The Initial Developer of the Original Code is Michael H. Kay.
576
//
577
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
578
//
579
// Contributor(s): none.
580
//
581
Popular Tags