1 /*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements. See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 /*
21 * $Id: LiteralElement.java,v 1.2.4.1 2005/09/13 12:38:33 pvedula Exp $
22 */
23
24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
25
26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
27 import com.sun.org.apache.bcel.internal.generic.InstructionList;
28 import com.sun.org.apache.bcel.internal.generic.PUSH;
29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
35 import com.sun.org.apache.xml.internal.serializer.ElemDesc;
36 import com.sun.org.apache.xml.internal.serializer.ToHTMLStream;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.Hashtable;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43
44 /**
45 * @author Jacek Ambroziak
46 * @author Santiago Pericas-Geertsen
47 * @author Morten Jorgensen
48 */
49 final class LiteralElement extends Instruction {
50
51 private String _name;
52 private LiteralElement _literalElemParent = null;
53 private List<SyntaxTreeNode> _attributeElements = null;
54 private Map<String, String> _accessedPrefixes = null;
55
56 // True if all attributes of this LRE are unique, i.e. they all have
57 // different names. This flag is set to false if some attribute
58 // names are not known at compile time.
59 private boolean _allAttributesUnique = false;
60
61 private final static String XMLNS_STRING = "xmlns";
62
63 /**
64 * Returns the QName for this literal element
65 */
66 public QName getName() {
67 return _qname;
68 }
69
70 /**
71 * Displays the contents of this literal element
72 */
73 public void display(int indent) {
74 indent(indent);
75 Util.println("LiteralElement name = " + _name);
76 displayContents(indent + IndentIncrement);
77 }
78
79 /**
80 * Returns the namespace URI for which a prefix is pointing to
81 */
82 private String accessedNamespace(String prefix) {
123 }
124
125 if (!prefix.equals("xml")) {
126 _accessedPrefixes.put(prefix,uri);
127 }
128 }
129
130 /**
131 * Translates the prefix of a QName according to the rules set in
132 * the attributes of xsl:stylesheet. Also registers a QName to assure
133 * that the output element contains the necessary namespace declarations.
134 */
135 private String translateQName(QName qname, SymbolTable stable) {
136 // Break up the QName and get prefix:localname strings
137 String localname = qname.getLocalPart();
138 String prefix = qname.getPrefix();
139
140 // Treat default namespace as "" and not null
141 if (prefix == null)
142 prefix = Constants.EMPTYSTRING;
143 else if (prefix.equals(XMLNS_STRING))
144 return(XMLNS_STRING);
145
146 // Check if we must translate the prefix
147 final String alternative = stable.lookupPrefixAlias(prefix);
148 if (alternative != null) {
149 stable.excludeNamespaces(prefix);
150 prefix = alternative;
151 }
152
153 // Get the namespace this prefix refers to
154 String uri = lookupNamespace(prefix);
155 if (uri == null) return(localname);
156
157 // Register the namespace as accessed
158 registerNamespace(prefix, uri, stable, false);
159
160 // Construct the new name for the element (may be unchanged)
161 if (prefix != Constants.EMPTYSTRING)
162 return(prefix+":"+localname);
163 else
164 return(localname);
247 // attributes can override an attributes in the set.
248 if (qname.equals(parser.getUseAttributeSets())) {
249 if (!Util.isValidQNames(val)) {
250 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, val, this);
251 parser.reportError(Constants.ERROR, err);
252 }
253 setFirstAttribute(new UseAttributeSets(val, parser));
254 }
255 // Handle xsl:extension-element-prefixes
256 else if (qname.equals(parser.getExtensionElementPrefixes())) {
257 stable.excludeNamespaces(val);
258 }
259 // Handle xsl:exclude-result-prefixes
260 else if (qname.equals(parser.getExcludeResultPrefixes())) {
261 stable.excludeNamespaces(val);
262 }
263 else {
264 // Ignore special attributes (e.g. xmlns:prefix and xmlns)
265 final String prefix = qname.getPrefix();
266 if (prefix != null && prefix.equals(XMLNS_PREFIX) ||
267 prefix == null && qname.getLocalPart().equals("xmlns") ||
268 uri != null && uri.equals(XSLT_URI))
269 {
270 continue;
271 }
272
273 // Handle all other literal attributes
274 final String name = translateQName(qname, stable);
275 LiteralAttribute attr = new LiteralAttribute(name, val, parser, this);
276 addAttribute(attr);
277 attr.setParent(this);
278 attr.parseContents(parser);
279 }
280 }
281
282 // Register all namespaces that are in scope, except for those that
283 // are listed in the xsl:stylesheet element's *-prefixes attributes
284 Set<Map.Entry<String, String>> include = getNamespaceScope(this);
285 for (Map.Entry<String, String> entry : include) {
286 final String prefix = entry.getKey();
287 if (!prefix.equals("xml")) {
320 * then the element contents, and then the element end tag. Since the
321 * value of an attribute may depend on a variable, variables must be
322 * compiled first.
323 */
324 public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
325
326 final ConstantPoolGen cpg = classGen.getConstantPool();
327 final InstructionList il = methodGen.getInstructionList();
328
329 // Check whether all attributes are unique.
330 _allAttributesUnique = checkAttributesUnique();
331
332 // Compile code to emit element start tag
333 il.append(methodGen.loadHandler());
334
335 il.append(new PUSH(cpg, _name));
336 il.append(DUP2); // duplicate these 2 args for endElement
337 il.append(methodGen.startElement());
338
339 // The value of an attribute may depend on a (sibling) variable
340 int j=0;
341 while (j < elementCount()) {
342 final SyntaxTreeNode item = (SyntaxTreeNode) elementAt(j);
343 if (item instanceof Variable) {
344 item.translate(classGen, methodGen);
345 }
346 j++;
347 }
348
349 // Compile code to emit namespace attributes
350 if (_accessedPrefixes != null) {
351 boolean declaresDefaultNS = false;
352
353 for (Map.Entry<String, String> entry : _accessedPrefixes.entrySet()) {
354 final String prefix = entry.getKey();
355 final String uri = entry.getValue();
356
357 if (uri != Constants.EMPTYSTRING ||
358 prefix != Constants.EMPTYSTRING)
359 {
360 if (prefix == Constants.EMPTYSTRING) {
361 declaresDefaultNS = true;
362 }
363 il.append(methodGen.loadHandler());
364 il.append(new PUSH(cpg,prefix));
365 il.append(new PUSH(cpg,uri));
366 il.append(methodGen.namespace());
367 }
368 }
369
370 /*
371 * If our XslElement parent redeclares the default NS, and this
372 * element doesn't, it must be redeclared one more time.
373 */
374 if (!declaresDefaultNS && (_parent instanceof XslElement)
375 && ((XslElement) _parent).declaresDefaultNS())
376 {
377 il.append(methodGen.loadHandler());
378 il.append(new PUSH(cpg, Constants.EMPTYSTRING));
379 il.append(new PUSH(cpg, Constants.EMPTYSTRING));
380 il.append(methodGen.namespace());
381 }
382 }
383
384 // Output all attributes
385 if (_attributeElements != null) {
386 for (SyntaxTreeNode node : _attributeElements) {
387 if (!(node instanceof XslAttribute)) {
388 node.translate(classGen, methodGen);
389 }
390 }
391 }
392
393 // Compile code to emit attributes and child elements
394 translateContents(classGen, methodGen);
395
396 // Compile code to emit element end tag
397 il.append(methodGen.endElement());
398 }
399
|
1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * Licensed to the Apache Software Foundation (ASF) under one or more
6 * contributor license agreements. See the NOTICE file distributed with
7 * this work for additional information regarding copyright ownership.
8 * The ASF licenses this file to You under the Apache License, Version 2.0
9 * (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 package com.sun.org.apache.xalan.internal.xsltc.compiler;
22
23 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
24 import com.sun.org.apache.bcel.internal.generic.InstructionList;
25 import com.sun.org.apache.bcel.internal.generic.PUSH;
26 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
32 import com.sun.org.apache.xml.internal.serializer.ElemDesc;
33 import com.sun.org.apache.xml.internal.serializer.ToHTMLStream;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.Hashtable;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40
41 /**
42 * @author Jacek Ambroziak
43 * @author Santiago Pericas-Geertsen
44 * @author Morten Jorgensen
45 */
46 final class LiteralElement extends Instruction {
47
48 private String _name;
49 private LiteralElement _literalElemParent = null;
50 private List<SyntaxTreeNode> _attributeElements = null;
51 private Map<String, String> _accessedPrefixes = null;
52
53 // True if all attributes of this LRE are unique, i.e. they all have
54 // different names. This flag is set to false if some attribute
55 // names are not known at compile time.
56 private boolean _allAttributesUnique = false;
57
58 /**
59 * Returns the QName for this literal element
60 */
61 public QName getName() {
62 return _qname;
63 }
64
65 /**
66 * Displays the contents of this literal element
67 */
68 public void display(int indent) {
69 indent(indent);
70 Util.println("LiteralElement name = " + _name);
71 displayContents(indent + IndentIncrement);
72 }
73
74 /**
75 * Returns the namespace URI for which a prefix is pointing to
76 */
77 private String accessedNamespace(String prefix) {
118 }
119
120 if (!prefix.equals("xml")) {
121 _accessedPrefixes.put(prefix,uri);
122 }
123 }
124
125 /**
126 * Translates the prefix of a QName according to the rules set in
127 * the attributes of xsl:stylesheet. Also registers a QName to assure
128 * that the output element contains the necessary namespace declarations.
129 */
130 private String translateQName(QName qname, SymbolTable stable) {
131 // Break up the QName and get prefix:localname strings
132 String localname = qname.getLocalPart();
133 String prefix = qname.getPrefix();
134
135 // Treat default namespace as "" and not null
136 if (prefix == null)
137 prefix = Constants.EMPTYSTRING;
138 else if (prefix.equals(XMLNS_PREFIX))
139 return(XMLNS_PREFIX);
140
141 // Check if we must translate the prefix
142 final String alternative = stable.lookupPrefixAlias(prefix);
143 if (alternative != null) {
144 stable.excludeNamespaces(prefix);
145 prefix = alternative;
146 }
147
148 // Get the namespace this prefix refers to
149 String uri = lookupNamespace(prefix);
150 if (uri == null) return(localname);
151
152 // Register the namespace as accessed
153 registerNamespace(prefix, uri, stable, false);
154
155 // Construct the new name for the element (may be unchanged)
156 if (prefix != Constants.EMPTYSTRING)
157 return(prefix+":"+localname);
158 else
159 return(localname);
242 // attributes can override an attributes in the set.
243 if (qname.equals(parser.getUseAttributeSets())) {
244 if (!Util.isValidQNames(val)) {
245 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, val, this);
246 parser.reportError(Constants.ERROR, err);
247 }
248 setFirstAttribute(new UseAttributeSets(val, parser));
249 }
250 // Handle xsl:extension-element-prefixes
251 else if (qname.equals(parser.getExtensionElementPrefixes())) {
252 stable.excludeNamespaces(val);
253 }
254 // Handle xsl:exclude-result-prefixes
255 else if (qname.equals(parser.getExcludeResultPrefixes())) {
256 stable.excludeNamespaces(val);
257 }
258 else {
259 // Ignore special attributes (e.g. xmlns:prefix and xmlns)
260 final String prefix = qname.getPrefix();
261 if (prefix != null && prefix.equals(XMLNS_PREFIX) ||
262 prefix == null && qname.getLocalPart().equals(XMLNS_PREFIX) ||
263 uri != null && uri.equals(XSLT_URI))
264 {
265 continue;
266 }
267
268 // Handle all other literal attributes
269 final String name = translateQName(qname, stable);
270 LiteralAttribute attr = new LiteralAttribute(name, val, parser, this);
271 addAttribute(attr);
272 attr.setParent(this);
273 attr.parseContents(parser);
274 }
275 }
276
277 // Register all namespaces that are in scope, except for those that
278 // are listed in the xsl:stylesheet element's *-prefixes attributes
279 Set<Map.Entry<String, String>> include = getNamespaceScope(this);
280 for (Map.Entry<String, String> entry : include) {
281 final String prefix = entry.getKey();
282 if (!prefix.equals("xml")) {
315 * then the element contents, and then the element end tag. Since the
316 * value of an attribute may depend on a variable, variables must be
317 * compiled first.
318 */
319 public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
320
321 final ConstantPoolGen cpg = classGen.getConstantPool();
322 final InstructionList il = methodGen.getInstructionList();
323
324 // Check whether all attributes are unique.
325 _allAttributesUnique = checkAttributesUnique();
326
327 // Compile code to emit element start tag
328 il.append(methodGen.loadHandler());
329
330 il.append(new PUSH(cpg, _name));
331 il.append(DUP2); // duplicate these 2 args for endElement
332 il.append(methodGen.startElement());
333
334 // The value of an attribute may depend on a (sibling) variable
335 int j = 0;
336 while (j < elementCount()) {
337 final SyntaxTreeNode item = elementAt(j);
338 if (item instanceof Variable) {
339 item.translate(classGen, methodGen);
340 }
341 j++;
342 }
343
344 // Compile code to emit namespace attributes
345 if (_accessedPrefixes != null) {
346 for (Map.Entry<String, String> entry : _accessedPrefixes.entrySet()) {
347 final String prefix = entry.getKey();
348 final String uri = entry.getValue();
349 il.append(methodGen.loadHandler());
350 il.append(new PUSH(cpg, prefix));
351 il.append(new PUSH(cpg, uri));
352 il.append(methodGen.namespace());
353 }
354 }
355
356 // Output all attributes
357 if (_attributeElements != null) {
358 for (SyntaxTreeNode node : _attributeElements) {
359 if (!(node instanceof XslAttribute)) {
360 node.translate(classGen, methodGen);
361 }
362 }
363 }
364
365 // Compile code to emit attributes and child elements
366 translateContents(classGen, methodGen);
367
368 // Compile code to emit element end tag
369 il.append(methodGen.endElement());
370 }
371
|