KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > style > LiteralResultElement


1 package com.icl.saxon.style;
2 import com.icl.saxon.Context;
3 import com.icl.saxon.PreparedStyleSheet;
4 import com.icl.saxon.om.Name;
5 import com.icl.saxon.om.NamePool;
6 import com.icl.saxon.om.Namespace;
7 import com.icl.saxon.tree.TreeBuilder;
8 import com.icl.saxon.tree.DocumentImpl;
9 import com.icl.saxon.expr.Expression;
10 import com.icl.saxon.expr.StringValue;
11 import com.icl.saxon.output.Outputter;
12 import javax.xml.transform.TransformerException JavaDoc;
13 import javax.xml.transform.TransformerConfigurationException JavaDoc;
14 import org.xml.sax.helpers.AttributesImpl JavaDoc;
15
16
17 /**
18 * This class represents a literal result element in the style sheet
19 * (typically an HTML element to be output). <br>
20 * It is also used to represent unknown top-level elements, which are ignored.
21 */

22
23 public class LiteralResultElement extends StyleElement {
24
25     private int resultNameCode;
26     private int[] attributeNames;
27     private Expression[] attributeValues;
28     private boolean[] attributeChecked;
29     private int numberOfAttributes;
30     private boolean toplevel;
31     private int[] namespaceCodes;
32
33
34     /**
35     * Determine whether this type of element is allowed to contain a template-body
36     * @return true: yes, it may contain a template-body
37     */

38
39     public boolean mayContainTemplateBody() {
40         return true;
41     }
42
43     /**
44     * Process the attribute list
45     */

46
47     public void prepareAttributes() throws TransformerConfigurationException JavaDoc {
48         // processing of the attribute list is deferred until validate() time, so that
49
// namespaces can be translated if necessary using the namespace aliases in force
50
// for the stylesheet.
51
}
52
53     /**
54     * Validate that this node is OK
55     */

56
57     public void validate() throws TransformerConfigurationException JavaDoc {
58
59         toplevel = (getParentNode() instanceof XSLStyleSheet);
60         
61         StandardNames sn = getStandardNames();
62         resultNameCode = getNameCode();
63
64         NamePool namePool = getNamePool();
65         short elementURICode = namePool.getURICode(resultNameCode);
66                 
67         if (toplevel) {
68             // A top-level element can never be a "real" literal result element,
69
// but this class gets used for them anyway
70

71             if (elementURICode == 0) {
72                 compileError("Top level elements must have a non-null namespace URI");
73             }
74         } else {
75                         
76             // Build the list of output namespace nodes
77

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

84             // At 6.0 we'll try a different optimisation: if this LRE has a parent that is also
85
// an LRE, and if this LRE has no namespace declarations or xsl:exclude-result-prefixes
86
// attribute or xsl:extension-element-prefixes attribute of its own, and if this element
87
// name is in the same namespace as its parent, and if there are no attributes in a
88
// non-null namespace, then we don't need to output any namespace declarations to the
89
// result.
90

91             boolean optimizeNS = false;
92             if ((getParent() instanceof LiteralResultElement) &&
93                     (namespaceList==null || namespaceList.length==0) &&
94                     ( elementURICode ==
95                          namePool.getURICode(getParent().getFingerprint()))
96                     ) {
97                 optimizeNS = true;
98             }
99             if (optimizeNS) {
100                 for (int a=0; a<attributeList.getLength(); a++ ) {
101                     if (((attributeList.getNameCode(a)>>20)&0xff) != 0) { // prefix != ""
102
optimizeNS = false;
103                         break;
104                     }
105                 }
106             }
107                                     
108             if (optimizeNS) {
109                 namespaceCodes = new int[0];
110             } else {
111                 namespaceCodes = getNamespaceCodes();
112             }
113             
114             // apply any aliases required to create the list of output namespaces
115

116             XSLStyleSheet sheet = getPrincipalStyleSheet();
117             
118             if (sheet.hasNamespaceAliases()) {
119                 for (int i=0; i<namespaceCodes.length; i++) {
120                     // System.err.println("Examining namespace " + namespaceCodes[i]);
121
short scode = (short)(namespaceCodes[i]&0xffff);
122                     short rcode = sheet.getNamespaceAlias(scode);
123                     if (scode!=rcode) {
124                         // keep the prefix but change the URI
125
int prefixCode = namespaceCodes[i] & 0xffff0000;
126                         namespaceCodes[i] = prefixCode | rcode;
127                         // System.err.println("Aliased as " + namespaceCodes[i]);
128
}
129                 }
130        
131                 // determine if there is an alias for the namespace of the element name
132

133                 short ercode = sheet.getNamespaceAlias(elementURICode);
134
135                 if (ercode!=elementURICode) {
136                     elementURICode = ercode;
137                     resultNameCode = namePool.allocate(getPrefix(), ercode, getLocalName());
138                 }
139             }
140
141             // establish the names to be used for all the output attributes
142

143             int num = attributeList.getLength();
144             attributeNames = new int[num];
145             attributeValues = new Expression[num];
146             attributeChecked = new boolean[num];
147             short[] attributeURIs = new short[num];
148             numberOfAttributes = 0;
149
150             for (int i=0; i<num; i++) {
151
152                 int anameCode = attributeList.getNameCode(i);
153                 int alias = anameCode;
154                 int fp = anameCode & 0xfffff;
155                 short attURIcode = namePool.getURICode(anameCode);
156
157                 if (fp == sn.XSL_USE_ATTRIBUTE_SETS) {
158                     findAttributeSets(attributeList.getValue(i));
159                 } else if (fp == sn.XSL_EXTENSION_ELEMENT_PREFIXES) {
160                     // already dealt with
161
} else if (fp == sn.XSL_EXCLUDE_RESULT_PREFIXES) {
162                     // already dealt with
163
} else if (fp == sn.XSL_VERSION) {
164                     // already dealt with
165
} else {
166                     
167                     if (attURIcode==Namespace.XSLT_CODE) {
168                         compileError("Unknown XSL attribute " + namePool.getDisplayName(anameCode));
169                     }
170                     if (attURIcode!=0) { // attribute has a namespace prefix
171
short attAlias = sheet.getNamespaceAlias(attURIcode);
172                         if (attAlias != attURIcode) {
173                             String JavaDoc qName = namePool.getDisplayName(anameCode);
174                             String JavaDoc newPrefix = Name.getPrefix(qName);
175                             String JavaDoc newLocalName = Name.getLocalName(qName);
176                             // System.err.println("Aliasing " + namePool.getDisplayName(anameCode));
177
String JavaDoc newURI = namePool.getURIFromNamespaceCode(attAlias);
178                             alias = namePool.allocate(newPrefix, newURI, newLocalName);
179                             // System.err.println("... as " + namePool.getDisplayName(alias));
180
attURIcode = attAlias;
181                         }
182                     }
183
184                     attributeNames[numberOfAttributes] = alias;
185                     attributeURIs[numberOfAttributes] = attURIcode;
186                     Expression exp = makeAttributeValueTemplate(attributeList.getValue(i));
187                     attributeValues[numberOfAttributes] = exp;
188
189                     // if we can be sure the attribute value contains no special XML/HTML characters,
190
// we can save the trouble of checking it each time it is output.
191
// Note that the check includes non-ASCII characters, as these might need to be escaped in a
192
// URL (we don't yet know which output method will be used!)
193

194                     attributeChecked[numberOfAttributes] = false;
195                     boolean special = false;
196                     if (exp instanceof StringValue) {
197                         String JavaDoc val = ((StringValue)exp).asString();
198                         for (int k=0; k<val.length(); k++) {
199                             char c = val.charAt(k);
200                             if ((int)c<33 || (int)c>126 ||
201                                      c=='<' || c=='>' || c=='&' || c=='\"') {
202                                 special = true;
203                                 break;
204                              }
205                         }
206                         attributeChecked[numberOfAttributes] = !special;
207                     }
208                     numberOfAttributes++;
209                 }
210             }
211
212             // remove any namespaces that are on the exclude-result-prefixes list, unless it is
213
// the namespace of the element or an attribute
214

215             for (int n=0; n<namespaceCodes.length; n++) {
216                 short uricode = (short)(namespaceCodes[n] & 0xffff);
217                 if (isExcludedNamespace(uricode)) {
218                     
219                     boolean exclude = true;
220
221                     // check the element name
222

223                     if (uricode==elementURICode) {
224                         exclude = false;
225                     }
226
227                     // check the attribute names
228

229                     for (int a=0; a<numberOfAttributes; a++) {
230                         if (uricode==attributeURIs[a]) {
231                             exclude = false;
232                             break;
233                         }
234                     }
235
236                     // if the name isn't in use, exclude it from the output namespace list
237

238                     if (exclude) {
239                         namespaceCodes[n] = -1;
240                     }
241                 }
242             }
243
244         }
245     }
246
247     protected void validateChildren () throws TransformerConfigurationException JavaDoc {
248         // don't validate subtree rooted at a top-level user-defined element
249
if (!toplevel) {
250             super.validateChildren();
251         }
252     }
253     
254     /**
255     * Process the literal result element by copying it to the result tree
256     */

257
258     public void process(Context context) throws TransformerException JavaDoc
259     {
260         // top level elements in the stylesheet are ignored
261
if (toplevel) return;
262         
263         // output the start tag
264
Outputter o = context.getOutputter();
265         o.writeStartTag(resultNameCode);
266
267         // output the namespace list
268

269         for (int i=0; i<namespaceCodes.length; i++) {
270             if (namespaceCodes[i]!=-1) {
271                 o.writeNamespaceDeclaration(namespaceCodes[i]);
272             }
273         }
274
275         // output any attributes from xsl:use-attribute-set
276

277         processAttributeSets(context);
278
279         // evaluate AVT expressions and output the attributes (these may be overwritten later)
280

281         for (int i=0; i<numberOfAttributes; i++) {
282             int attname = attributeNames[i];
283             String JavaDoc attval = attributeValues[i].evaluateAsString(context);
284             o.writeAttribute(attname, attval, attributeChecked[i]);
285         }
286
287         // process the child elements in the stylesheet
288

289         processChildren(context);
290
291         // write the end tag
292

293         o.writeEndTag(resultNameCode);
294
295     }
296
297     /**
298     * Make a top-level literal result element into a stylesheet. This implements
299     * the "Literal Result Element As Stylesheet" facility.
300     */

301
302     public DocumentImpl makeStyleSheet(PreparedStyleSheet pss) throws TransformerConfigurationException JavaDoc {
303
304         // the implementation grafts the LRE node onto a containing xsl:template and
305
// xsl:stylesheet
306

307         NamePool pool = getNamePool();
308         StandardNames sn = getStandardNames();
309         String JavaDoc xslPrefix = getPrefixForURI(Namespace.XSLT);
310         if (xslPrefix==null) {
311             String JavaDoc message;
312             if (getLocalName().equals("stylesheet") || getLocalName().equals("transform")) {
313                 if (getPrefixForURI(Namespace.MICROSOFT_XSL)!=null) {
314                     message = "Saxon is not able to process Microsoft's WD-xsl dialect";
315                 } else {
316                     message = "Namespace for stylesheet element should be " + Namespace.XSLT;
317                 }
318             } else {
319                 message = "The supplied file does not appear to be a stylesheet";
320             }
321             TransformerConfigurationException JavaDoc err =
322                new TransformerConfigurationException JavaDoc (message);
323             try {pss.reportError(err);} catch(TransformerException JavaDoc err2) {}
324             throw err;
325                 
326         }
327
328         // check there is an xsl:version attribute (it's mandatory), and copy
329
// it to the new xsl:stylesheet element
330

331         String JavaDoc version = getAttributeValue(sn.XSL_VERSION);
332         if (version==null) {
333             TransformerConfigurationException JavaDoc err =
334                new TransformerConfigurationException JavaDoc (
335                 "Literal Result Element As Stylesheet: xsl:version attribute is missing");
336             try {pss.reportError(err);} catch(TransformerException JavaDoc err2) {}
337             throw err;
338         }
339
340         try {
341             TreeBuilder builder = new TreeBuilder();
342             builder.setDocumentLocator(null);
343             builder.setNamePool(pool);
344             builder.setNodeFactory(((DocumentImpl)getParentNode()).getNodeFactory());
345             builder.setSystemId(this.getSystemId());
346     
347             builder.startDocument();
348             AttributesImpl JavaDoc atts = new AttributesImpl JavaDoc();
349             atts.addAttribute("", "version", "version", "CDATA", version);
350             int[] namespaces = new int[1];
351             namespaces[0] = pool.getNamespaceCode("xsl", Namespace.XSLT);
352             int st = pool.allocate("xsl", Namespace.XSLT, "stylesheet");
353             builder.startElement(st, atts, namespaces, 1);
354     
355             int te = pool.allocate("xsl", Namespace.XSLT, "template");
356             atts.clear();
357             atts.addAttribute("", "match", "match", "CDATA", "/");
358             builder.startElement(te, atts, namespaces, 0);
359     
360             builder.graftElement(this);
361     
362             builder.endElement(te);
363             builder.endElement(st);
364             builder.endDocument();
365             
366             return (DocumentImpl)builder.getCurrentDocument();
367         } catch (TransformerException JavaDoc err) {
368             throw new TransformerConfigurationException JavaDoc(err);
369         }
370
371     }
372
373
374 }
375 //
376
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
377
// you may not use this file except in compliance with the License. You may obtain a copy of the
378
// License at http://www.mozilla.org/MPL/
379
//
380
// Software distributed under the License is distributed on an "AS IS" basis,
381
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
382
// See the License for the specific language governing rights and limitations under the License.
383
//
384
// The Original Code is: all this file.
385
//
386
// The Initial Developer of the Original Code is
387
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
388
//
389
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
390
//
391
// Contributor(s): none.
392
//
393
Popular Tags