KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.style;
2 import net.sf.saxon.event.SaxonOutputKeys;
3 import net.sf.saxon.expr.Expression;
4 import net.sf.saxon.instruct.Executable;
5 import net.sf.saxon.om.*;
6 import net.sf.saxon.trans.SaxonErrorCode;
7 import net.sf.saxon.trans.XPathException;
8
9 import javax.xml.transform.OutputKeys JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.Iterator JavaDoc;
12 import java.util.Properties JavaDoc;
13 import java.util.StringTokenizer JavaDoc;
14
15 /**
16 * An xsl:output element in the stylesheet.
17 */

18
19 public class XSLOutput extends StyleElement {
20
21     private int fingerprint = -1;
22     private String JavaDoc method = null;
23     private String JavaDoc version = null;
24     private String JavaDoc indent = null;
25     private String JavaDoc encoding = null;
26     private String JavaDoc mediaType = null;
27     private String JavaDoc doctypeSystem = null;
28     private String JavaDoc doctypePublic = null;
29     private String JavaDoc omitDeclaration = null;
30     private String JavaDoc standalone = null;
31     private String JavaDoc cdataElements = null;
32     private String JavaDoc includeContentType = null;
33     private String JavaDoc nextInChain = null;
34     private String JavaDoc representation = null;
35     private String JavaDoc indentSpaces = null;
36     private String JavaDoc byteOrderMark = null;
37     private String JavaDoc escapeURIAttributes = null;
38     private String JavaDoc normalizationForm = null;
39     private String JavaDoc requireWellFormed = null;
40     private String JavaDoc undeclareNamespaces = null;
41     private String JavaDoc useCharacterMaps = null;
42     private HashMap JavaDoc userAttributes = null;
43
44     //Emitter handler = null;
45

46     public void prepareAttributes() throws XPathException {
47         AttributeCollection atts = getAttributeList();
48         String JavaDoc nameAtt = null;
49
50         for (int a=0; a<atts.getLength(); a++) {
51             int nc = atts.getNameCode(a);
52             String JavaDoc f = getNamePool().getClarkName(nc);
53             if (f==StandardNames.NAME) {
54                 nameAtt = atts.getValue(a).trim();
55             } else if (f==StandardNames.METHOD) {
56                 method = atts.getValue(a).trim();
57             } else if (f==StandardNames.VERSION) {
58                 version = atts.getValue(a).trim();
59             } else if (f==StandardNames.BYTE_ORDER_MARK) {
60                 byteOrderMark = atts.getValue(a).trim();
61             } else if (f==StandardNames.ENCODING) {
62                 encoding = atts.getValue(a).trim();
63             } else if (f==StandardNames.OMIT_XML_DECLARATION) {
64                 omitDeclaration = atts.getValue(a).trim();
65             } else if (f==StandardNames.STANDALONE) {
66                 standalone = atts.getValue(a).trim();
67             } else if (f==StandardNames.DOCTYPE_PUBLIC) {
68                 doctypePublic = atts.getValue(a).trim();
69             } else if (f==StandardNames.DOCTYPE_SYSTEM) {
70                 doctypeSystem = atts.getValue(a).trim();
71             } else if (f==StandardNames.CDATA_SECTION_ELEMENTS) {
72                 cdataElements = atts.getValue(a);
73             } else if (f==StandardNames.INDENT) {
74                 indent = atts.getValue(a).trim();
75             } else if (f==StandardNames.MEDIA_TYPE) {
76                 mediaType = atts.getValue(a).trim();
77             } else if (f==StandardNames.INCLUDE_CONTENT_TYPE) {
78                 includeContentType = atts.getValue(a).trim();
79             } else if (f==StandardNames.NORMALIZATION_FORM) {
80                 normalizationForm = atts.getValue(a).trim();
81             } else if (f==StandardNames.ESCAPE_URI_ATTRIBUTES) {
82                 escapeURIAttributes = atts.getValue(a).trim();
83             } else if (f==StandardNames.USE_CHARACTER_MAPS) {
84                 useCharacterMaps = atts.getValue(a);
85             } else if (f==StandardNames.UNDECLARE_PREFIXES) {
86                 undeclareNamespaces = atts.getValue(a);
87             } else if (f==StandardNames.SAXON_CHARACTER_REPRESENTATION) {
88                 representation = atts.getValue(a).trim();
89             } else if (f==StandardNames.SAXON_INDENT_SPACES) {
90                 indentSpaces = atts.getValue(a).trim();
91             } else if (f==StandardNames.SAXON_NEXT_IN_CHAIN) {
92                 nextInChain = atts.getValue(a).trim();
93             } else if (f==StandardNames.SAXON_REQUIRE_WELL_FORMED) {
94                 requireWellFormed = atts.getValue(a).trim();
95             } else {
96                 String JavaDoc attributeURI = getNamePool().getURI(nc);
97                 if ("".equals(attributeURI) ||
98                         NamespaceConstant.XSLT.equals(attributeURI) ||
99                         NamespaceConstant.SAXON.equals(attributeURI)) {
100                     checkUnknownAttribute(nc);
101                 } else {
102                     String JavaDoc name = '{' + attributeURI + '}' + atts.getLocalName(a);
103                     if (userAttributes==null) {
104                         userAttributes = new HashMap JavaDoc(5);
105                     }
106                     userAttributes.put(name, atts.getValue(a));
107                 }
108             }
109         }
110         if (nameAtt!=null) {
111             try {
112                 fingerprint = makeNameCode(nameAtt.trim()) & 0xfffff;
113             } catch (NamespaceException err) {
114                 compileError(err.getMessage(), "XTSE1570");
115             } catch (XPathException err) {
116                 compileError(err.getMessage(), "XTSE1570");
117             }
118         }
119     }
120
121     /**
122      * Get the name of the xsl:output declaration
123      * @return the name, as a namepool fingerprint; or -1 for an unnamed output declaration
124      */

125
126     public int getOutputFingerprint() {
127         return fingerprint;
128     }
129
130     public void validate() throws XPathException {
131         checkTopLevel(null);
132         checkEmpty();
133     }
134
135     public Expression compile(Executable exec) {
136         return null;
137     }
138
139
140     /**
141     * Validate the properties,
142     * and return the values as additions to a supplied Properties object.
143     */

144
145     protected void gatherOutputProperties(Properties JavaDoc details, HashMap JavaDoc precedences)
146     throws XPathException {
147
148         if (method != null) {
149             if (method.equals("xml") || method.equals("html") ||
150                     method.equals("text") || method.equals("xhtml")) {
151                 checkAndPut(OutputKeys.METHOD, method, details, precedences);
152                 //details.put(OutputKeys.METHOD, method);
153
} else {
154                 String JavaDoc[] parts;
155                 try {
156                     parts = Name.getQNameParts(method);
157                     String JavaDoc prefix = parts[0];
158                     if (prefix.equals("")) {
159                         compileError("method must be xml, html, xhtml, or text, or a prefixed name", "XTSE1570");
160                     } else {
161                         String JavaDoc uri = getURIForPrefix(prefix, false);
162                         if (uri == null) {
163                             undeclaredNamespaceError(prefix, "XTSE0280");
164                         }
165                         checkAndPut(OutputKeys.METHOD, '{' + uri + '}' + parts[1], details, precedences);
166                         //details.put(OutputKeys.METHOD, '{' + uri + '}' + parts[1] );
167
}
168                 } catch (QNameException e) {
169                     compileError("Invalid method name. " + e.getMessage(), "XTSE1570");
170                 }
171             }
172         }
173
174         if (byteOrderMark != null) {
175             if (byteOrderMark.equals("yes") || byteOrderMark.equals("no")) {
176                 checkAndPut(SaxonOutputKeys.BYTE_ORDER_MARK, byteOrderMark, details, precedences);
177                 //details.put(SaxonOutputKeys.BYTE_ORDER_MARK, byteOrderMark);
178
} else {
179                 compileError("byte-order-mark value must be 'yes' or 'no'", "XTSE0020");
180             }
181         }
182
183         if (version != null) {
184             checkAndPut(OutputKeys.VERSION, version, details, precedences);
185             //details.put(OutputKeys.VERSION, version);
186
}
187
188         if (indent != null) {
189             if (indent.equals("yes") || indent.equals("no")) {
190                 //details.put(OutputKeys.INDENT, indent);
191
checkAndPut(OutputKeys.INDENT, indent, details, precedences);
192             } else {
193                 compileError("indent value must be 'yes' or 'no'", "XTSE0020");
194             }
195         }
196
197         if (indentSpaces != null) {
198             try {
199                 Integer.parseInt(indentSpaces);
200                 details.put(OutputKeys.INDENT, "yes");
201                 checkAndPut(SaxonOutputKeys.INDENT_SPACES, indentSpaces, details, precedences);
202                 //details.put(SaxonOutputKeys.INDENT_SPACES, indentSpaces);
203
} catch (NumberFormatException JavaDoc err) {
204                 compileWarning("saxon:indent-spaces must be an integer. Using default value (3).",
205                         SaxonErrorCode.SXWN9002);
206             }
207         }
208
209         if (encoding != null) {
210             checkAndPut(OutputKeys.ENCODING, encoding, details, precedences);
211             //details.put(OutputKeys.ENCODING, encoding);
212
}
213
214         if (mediaType != null) {
215             checkAndPut(OutputKeys.MEDIA_TYPE, mediaType, details, precedences);
216             //details.put(OutputKeys.MEDIA_TYPE, mediaType);
217
}
218
219         if (doctypeSystem != null) {
220             checkAndPut(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem, details, precedences);
221             //details.put(OutputKeys.DOCTYPE_SYSTEM, doctypeSystem);
222
}
223
224         if (doctypePublic != null) {
225             checkAndPut(OutputKeys.DOCTYPE_PUBLIC, doctypePublic, details, precedences);
226             //details.put(OutputKeys.DOCTYPE_PUBLIC, doctypePublic);
227
}
228
229         if (omitDeclaration != null) {
230             if (omitDeclaration.equals("yes") || omitDeclaration.equals("no")) {
231                 checkAndPut(OutputKeys.OMIT_XML_DECLARATION, omitDeclaration, details, precedences);
232                 //details.put(OutputKeys.OMIT_XML_DECLARATION, omitDeclaration);
233
} else {
234                 compileError("omit-xml-declaration attribute must be 'yes' or 'no'", "XTSE0020");
235             }
236         }
237
238         if (standalone != null) {
239             if (standalone.equals("yes") || standalone.equals("no") || standalone.equals("omit")) {
240                 checkAndPut(OutputKeys.STANDALONE, standalone, details, precedences);
241                 //details.put(OutputKeys.STANDALONE, standalone);
242
} else {
243                 compileError("standalone attribute must be 'yes' or 'no' or 'omit'", "XTSE0020");
244             }
245         }
246
247         if (cdataElements != null) {
248             String JavaDoc existing = details.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
249             if (existing==null) {
250                 existing = "";
251             }
252             String JavaDoc s = "";
253             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(cdataElements);
254             while (st.hasMoreTokens()) {
255                 String JavaDoc displayname = st.nextToken();
256                 try {
257                     String JavaDoc[] parts = Name.getQNameParts(displayname);
258                     String JavaDoc uri = getURIForPrefix(parts[0], true);
259                     if (uri == null) {
260                         undeclaredNamespaceError(parts[0], "XTSE0280");
261                     }
262                     s += " {" + uri + '}' + parts[1];
263                 } catch (QNameException err) {
264                     compileError("Invalid CDATA element name. " + err.getMessage(), "XTSE0280");
265                 }
266
267                 details.put(OutputKeys.CDATA_SECTION_ELEMENTS, existing+s);
268             }
269         }
270
271         if (normalizationForm != null && !normalizationForm.equals("none")) {
272             if (normalizationForm.equals("NFC") || normalizationForm.equals("NFD") ||
273                    normalizationForm.equals("NFKC") || normalizationForm.equals("NFKD") ) {
274                 checkAndPut(SaxonOutputKeys.NORMALIZATION_FORM, normalizationForm, details, precedences);
275             } else {
276                 compileError("normalization-form must be one of NFC, NFD, NFKC, NFKD, or 'none'", "XTSE0020");
277             }
278         }
279
280         if (undeclareNamespaces != null) {
281             if (undeclareNamespaces.equals("yes") || undeclareNamespaces.equals("no")) {
282                 checkAndPut(SaxonOutputKeys.UNDECLARE_PREFIXES, undeclareNamespaces, details, precedences);
283                 //details.put(SaxonOutputKeys.UNDECLARE_PREFIXES, undeclareNamespaces);
284
} else {
285                 compileError("undeclare-namespaces value must be 'yes' or 'no'", "XTSE0020");
286             }
287         }
288
289         if (useCharacterMaps != null) {
290             String JavaDoc s = prepareCharacterMaps(this, useCharacterMaps, details);
291             details.put(SaxonOutputKeys.USE_CHARACTER_MAPS, s);
292         }
293
294         if (representation != null) {
295             checkAndPut(SaxonOutputKeys.CHARACTER_REPRESENTATION, representation, details, precedences);
296             //details.put(SaxonOutputKeys.CHARACTER_REPRESENTATION, representation);
297
}
298
299         if (includeContentType != null) {
300             if (includeContentType.equals("yes") || includeContentType.equals("no")) {
301                 checkAndPut(SaxonOutputKeys.INCLUDE_CONTENT_TYPE, includeContentType, details, precedences);
302                 //details.put(SaxonOutputKeys.INCLUDE_CONTENT_TYPE, includeContentType);
303
} else {
304                 compileError("include-content-type attribute must be 'yes' or 'no'", "XTSE0020");
305             }
306         }
307
308         if (escapeURIAttributes != null) {
309             if (escapeURIAttributes.equals("yes") || escapeURIAttributes.equals("no")) {
310                 checkAndPut(SaxonOutputKeys.ESCAPE_URI_ATTRIBUTES, escapeURIAttributes, details, precedences);
311                 //details.put(SaxonOutputKeys.ESCAPE_URI_ATTRIBUTES, escapeURIAttributes);
312
} else {
313                 compileError("escape-uri-attributes value must be 'yes' or 'no'", "XTSE0020");
314             }
315         }
316
317         if (nextInChain != null) {
318             checkAndPut(SaxonOutputKeys.NEXT_IN_CHAIN, nextInChain, details, precedences);
319             checkAndPut(SaxonOutputKeys.NEXT_IN_CHAIN_BASE_URI, getSystemId(), details, precedences);
320             //details.put(SaxonOutputKeys.NEXT_IN_CHAIN, nextInChain);
321
//details.put(SaxonOutputKeys.NEXT_IN_CHAIN_BASE_URI, getSystemId());
322
}
323
324         if (requireWellFormed != null) {
325             if (requireWellFormed.equals("yes") || requireWellFormed.equals("no")) {
326                 checkAndPut(SaxonOutputKeys.REQUIRE_WELL_FORMED, requireWellFormed, details, precedences);
327                 //details.put(SaxonOutputKeys.REQUIRE_WELL_FORMED, requireWellFormed);
328
} else {
329                 compileWarning("saxon:require-well-formed value must be 'yes' or 'no' (treated as no)",
330                         SaxonErrorCode.SXWN9003);
331             }
332         }
333
334         // deal with user-defined attributes
335

336         if (userAttributes!=null) {
337             Iterator JavaDoc iter = userAttributes.keySet().iterator();
338             while (iter.hasNext()) {
339                 String JavaDoc attName = (String JavaDoc)iter.next();
340                 String JavaDoc data = (String JavaDoc)userAttributes.get(attName);
341                 details.put(attName, data);
342             }
343         }
344
345     }
346
347     /**
348      * Add an output property to the list of properties after checking that it is consistent
349      * with other properties
350      */

351
352     public void checkAndPut(String JavaDoc property, String JavaDoc value, Properties JavaDoc props, HashMap JavaDoc precedences)
353             throws XPathException {
354         String JavaDoc old = props.getProperty(property);
355         if (old == null) {
356             props.setProperty(property, value);
357             precedences.put(property, new Integer JavaDoc(getPrecedence()));
358         } else if (old.equals(value)) {
359             // do nothing
360
} else {
361             Integer JavaDoc oldPrec = (Integer JavaDoc)precedences.get(property);
362             if (oldPrec == null) return; // shouldn't happen but ignore it
363
int op = oldPrec.intValue();
364             if (op > getPrecedence()) {
365                 // ignore this value, the other has higher precedence
366
} else if (op == getPrecedence()) {
367                 compileError("Conflicting values for output property " + property, "XTSE1560");
368             } else {
369                 // this has higher precedence: can't happen
370
throw new IllegalStateException JavaDoc("Output properties must be processed in decreasing precedence order");
371             }
372         }
373     }
374
375     /**
376      * Process the use-character-maps attribute
377      * @param details The output details to received the processed value
378      * @throws XPathException if the value is invalid
379      */

380     public static String JavaDoc prepareCharacterMaps(StyleElement element,
381                                             String JavaDoc useCharacterMaps,
382                                             Properties JavaDoc details)
383             throws XPathException {
384         XSLStylesheet principal = element.getPrincipalStylesheet();
385         String JavaDoc existing = details.getProperty(SaxonOutputKeys.USE_CHARACTER_MAPS);
386         if (existing==null) {
387             existing = "";
388         }
389         String JavaDoc s = "";
390         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(useCharacterMaps);
391         while (st.hasMoreTokens()) {
392             String JavaDoc displayname = st.nextToken();
393             try {
394                 String JavaDoc[] parts = Name.getQNameParts(displayname);
395                 String JavaDoc uri = element.getURIForPrefix(parts[0], false);
396                 if (uri == null) {
397                     element.undeclaredNamespaceError(parts[0], "XT0280");
398                 }
399                 int nameCode = element.getTargetNamePool().allocate(parts[0], uri, parts[1]);
400                 XSLCharacterMap ref =
401                         principal.getCharacterMap(nameCode & 0xfffff);
402                 if (ref == null) {
403                     element.compileError("No character-map named '" + displayname + "' has been defined", "XTSE1590");
404                 }
405                 s += " {" + uri + '}' + parts[1];
406             } catch (QNameException err) {
407                 element.compileError("Invalid character-map name. " + err.getMessage(), "XTSE1590");
408             }
409
410         }
411         existing = s + existing;
412         return existing;
413     }
414
415 }
416
417 //
418
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
419
// you may not use this file except in compliance with the License. You may obtain a copy of the
420
// License at http://www.mozilla.org/MPL/
421
//
422
// Software distributed under the License is distributed on an "AS IS" basis,
423
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
424
// See the License for the specific language governing rights and limitations under the License.
425
//
426
// The Original Code is: all this file.
427
//
428
// The Initial Developer of the Original Code is Michael H. Kay.
429
//
430
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
431
//
432
// Contributor(s): none.
433
//
434
Popular Tags