< prev index next >

src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/LiteralElement.java

Print this page
rev 959 : 8162598: XSLTC transformer swallows empty namespace declaration which is needed to undeclare default namespace
   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 


< prev index next >