Home | History | Annotate | Download | only in templates
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: ElemAttribute.java 469304 2006-10-30 22:29:47Z minchau $
     20  */
     21 package org.apache.xalan.templates;
     22 
     23 import javax.xml.transform.TransformerException;
     24 
     25 import org.apache.xalan.res.XSLTErrorResources;
     26 import org.apache.xalan.transformer.TransformerImpl;
     27 import org.apache.xml.serializer.NamespaceMappings;
     28 import org.apache.xml.serializer.SerializationHandler;
     29 import org.apache.xml.utils.QName;
     30 import org.apache.xml.utils.XML11Char;
     31 
     32 import org.xml.sax.SAXException;
     33 
     34 /**
     35  * Implement xsl:attribute.
     36  * <pre>
     37  * &amp;!ELEMENT xsl:attribute %char-template;>
     38  * &amp;!ATTLIST xsl:attribute
     39  *   name %avt; #REQUIRED
     40  *   namespace %avt; #IMPLIED
     41  *   %space-att;
     42  * &amp;
     43  * </pre>
     44  * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
     45  * @xsl.usage advanced
     46  */
     47 public class ElemAttribute extends ElemElement
     48 {
     49     static final long serialVersionUID = 8817220961566919187L;
     50 
     51   /**
     52    * Get an int constant identifying the type of element.
     53    * @see org.apache.xalan.templates.Constants
     54    *
     55    * @return The token ID for this element
     56    */
     57   public int getXSLToken()
     58   {
     59     return Constants.ELEMNAME_ATTRIBUTE;
     60   }
     61 
     62   /**
     63    * Return the node name.
     64    *
     65    * @return The element name
     66    */
     67   public String getNodeName()
     68   {
     69     return Constants.ELEMNAME_ATTRIBUTE_STRING;
     70   }
     71 
     72   /**
     73    * Create an attribute in the result tree.
     74    * @see <a href="http://www.w3.org/TR/xslt#creating-attributes">creating-attributes in XSLT Specification</a>
     75    *
     76    * @param transformer non-null reference to the the current transform-time state.
     77    *
     78    * @throws TransformerException
     79    */
     80 //  public void execute(
     81 //          TransformerImpl transformer)
     82 //            throws TransformerException
     83 //  {
     84     //SerializationHandler rhandler = transformer.getSerializationHandler();
     85 
     86     // If they are trying to add an attribute when there isn't an
     87     // element pending, it is an error.
     88     // I don't think we need this check here because it is checked in
     89     // ResultTreeHandler.addAttribute.  (is)
     90 //    if (!rhandler.isElementPending())
     91 //    {
     92 //      // Make sure the trace event is sent.
     93 //      if (TransformerImpl.S_DEBUG)
     94 //        transformer.getTraceManager().fireTraceEvent(this);
     95 //
     96 //      XPathContext xctxt = transformer.getXPathContext();
     97 //      int sourceNode = xctxt.getCurrentNode();
     98 //      String attrName = m_name_avt.evaluate(xctxt, sourceNode, this);
     99 //      transformer.getMsgMgr().warn(this,
    100 //                                   XSLTErrorResources.WG_ILLEGAL_ATTRIBUTE_POSITION,
    101 //                                   new Object[]{ attrName });
    102 //
    103 //      if (TransformerImpl.S_DEBUG)
    104 //        transformer.getTraceManager().fireTraceEndEvent(this);
    105 //      return;
    106 //
    107 //      // warn(templateChild, sourceNode, "Trying to add attribute after element child has been added, ignoring...");
    108 //    }
    109 
    110 //    super.execute(transformer);
    111 
    112 //  }
    113 
    114   /**
    115    * Resolve the namespace into a prefix.  At this level, if no prefix exists,
    116    * then return a manufactured prefix.
    117    *
    118    * @param rhandler The current result tree handler.
    119    * @param prefix The probable prefix if already known.
    120    * @param nodeNamespace  The namespace, which should not be null.
    121    *
    122    * @return The prefix to be used.
    123    */
    124   protected String resolvePrefix(SerializationHandler rhandler,
    125                                  String prefix, String nodeNamespace)
    126     throws TransformerException
    127   {
    128 
    129     if (null != prefix && (prefix.length() == 0 || prefix.equals("xmlns")))
    130     {
    131       // Since we can't use default namespace, in this case we try and
    132       // see if a prefix has already been defined or this namespace.
    133       prefix = rhandler.getPrefix(nodeNamespace);
    134 
    135       // System.out.println("nsPrefix: "+nsPrefix);
    136       if (null == prefix || prefix.length() == 0 || prefix.equals("xmlns"))
    137       {
    138         if(nodeNamespace.length() > 0)
    139         {
    140             NamespaceMappings prefixMapping = rhandler.getNamespaceMappings();
    141             prefix = prefixMapping.generateNextPrefix();
    142         }
    143         else
    144           prefix = "";
    145       }
    146     }
    147     return prefix;
    148   }
    149 
    150   /**
    151    * Validate that the node name is good.
    152    *
    153    * @param nodeName Name of the node being constructed, which may be null.
    154    *
    155    * @return true if the node name is valid, false otherwise.
    156    */
    157    protected boolean validateNodeName(String nodeName)
    158    {
    159       if(null == nodeName)
    160         return false;
    161       if(nodeName.equals("xmlns"))
    162         return false;
    163       return XML11Char.isXML11ValidQName(nodeName);
    164    }
    165 
    166   /**
    167    * Construct a node in the result tree.  This method is overloaded by
    168    * xsl:attribute. At this class level, this method creates an element.
    169    *
    170    * @param nodeName The name of the node, which may be null.
    171    * @param prefix The prefix for the namespace, which may be null.
    172    * @param nodeNamespace The namespace of the node, which may be null.
    173    * @param transformer non-null reference to the the current transform-time state.
    174    * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
    175    * @param mode reference, which may be null, to the <a href="http://www.w3.org/TR/xslt#modes">current mode</a>.
    176    *
    177    * @throws TransformerException
    178    */
    179   void constructNode(
    180           String nodeName, String prefix, String nodeNamespace, TransformerImpl transformer)
    181             throws TransformerException
    182   {
    183 
    184     if(null != nodeName && nodeName.length() > 0)
    185     {
    186       SerializationHandler rhandler = transformer.getSerializationHandler();
    187 
    188       // Evaluate the value of this attribute
    189       String val = transformer.transformToString(this);
    190       try
    191       {
    192         // Let the result tree handler add the attribute and its String value.
    193         String localName = QName.getLocalPart(nodeName);
    194         if(prefix != null && prefix.length() > 0){
    195             rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val, true);
    196         }else{
    197             rhandler.addAttribute("", localName, nodeName, "CDATA", val, true);
    198         }
    199       }
    200       catch (SAXException e)
    201       {
    202       }
    203     }
    204   }
    205 
    206 
    207   /**
    208    * Add a child to the child list.
    209    * <!ELEMENT xsl:attribute %char-template;>
    210    * <!ATTLIST xsl:attribute
    211    *   name %avt; #REQUIRED
    212    *   namespace %avt; #IMPLIED
    213    *   %space-att;
    214    * >
    215    *
    216    * @param newChild Child to append to the list of this node's children
    217    *
    218    * @return The node we just appended to the children list
    219    *
    220    * @throws DOMException
    221    */
    222   public ElemTemplateElement appendChild(ElemTemplateElement newChild)
    223   {
    224 
    225     int type = ((ElemTemplateElement) newChild).getXSLToken();
    226 
    227     switch (type)
    228     {
    229 
    230     // char-instructions
    231     case Constants.ELEMNAME_TEXTLITERALRESULT :
    232     case Constants.ELEMNAME_APPLY_TEMPLATES :
    233     case Constants.ELEMNAME_APPLY_IMPORTS :
    234     case Constants.ELEMNAME_CALLTEMPLATE :
    235     case Constants.ELEMNAME_FOREACH :
    236     case Constants.ELEMNAME_VALUEOF :
    237     case Constants.ELEMNAME_COPY_OF :
    238     case Constants.ELEMNAME_NUMBER :
    239     case Constants.ELEMNAME_CHOOSE :
    240     case Constants.ELEMNAME_IF :
    241     case Constants.ELEMNAME_TEXT :
    242     case Constants.ELEMNAME_COPY :
    243     case Constants.ELEMNAME_VARIABLE :
    244     case Constants.ELEMNAME_MESSAGE :
    245 
    246       // instructions
    247       // case Constants.ELEMNAME_PI:
    248       // case Constants.ELEMNAME_COMMENT:
    249       // case Constants.ELEMNAME_ELEMENT:
    250       // case Constants.ELEMNAME_ATTRIBUTE:
    251       break;
    252     default :
    253       error(XSLTErrorResources.ER_CANNOT_ADD,
    254             new Object[]{ newChild.getNodeName(),
    255                           this.getNodeName() });  //"Can not add " +((ElemTemplateElement)newChild).m_elemName +
    256 
    257     //" to " + this.m_elemName);
    258     }
    259 
    260     return super.appendChild(newChild);
    261   }
    262 	/**
    263 	 * @see ElemElement#setName(AVT)
    264 	 */
    265 	public void setName(AVT v) {
    266         if (v.isSimple())
    267         {
    268             if (v.getSimpleString().equals("xmlns"))
    269             {
    270                 throw new IllegalArgumentException();
    271             }
    272         }
    273 		super.setName(v);
    274 	}
    275 
    276 }
    277