Home | History | Annotate | Download | only in processor
      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: XSLTElementProcessor.java 469688 2006-10-31 22:39:43Z minchau $
     20  */
     21 package org.apache.xalan.processor;
     22 
     23 import java.util.ArrayList;
     24 import java.util.List;
     25 import java.util.Vector;
     26 
     27 import javax.xml.transform.TransformerException;
     28 
     29 import org.apache.xalan.res.XSLMessages;
     30 import org.apache.xalan.res.XSLTErrorResources;
     31 import org.apache.xalan.templates.ElemTemplateElement;
     32 import org.apache.xml.utils.IntStack;
     33 import org.xml.sax.Attributes;
     34 import org.xml.sax.InputSource;
     35 import org.xml.sax.helpers.AttributesImpl;
     36 
     37 /**
     38  * This class acts as the superclass for all stylesheet element
     39  * processors, and deals with things that are common to all elements.
     40  * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
     41  */
     42 public class XSLTElementProcessor extends ElemTemplateElement
     43 {
     44     static final long serialVersionUID = 5597421564955304421L;
     45 
     46   /**
     47    * Construct a processor for top-level elements.
     48    * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
     49    */
     50   XSLTElementProcessor(){}
     51 
     52 	private IntStack m_savedLastOrder;
     53 
     54   /**
     55    * The element definition that this processor conforms to.
     56    */
     57   private XSLTElementDef m_elemDef;
     58 
     59   /**
     60    * Get the element definition that belongs to this element.
     61    *
     62    * @return The element definition object that produced and constrains this element.
     63    */
     64   XSLTElementDef getElemDef()
     65   {
     66     return m_elemDef;
     67   }
     68 
     69   /**
     70    * Set the element definition that belongs to this element.
     71    *
     72    * @param def The element definition object that produced and constrains this element.
     73    */
     74   void setElemDef(XSLTElementDef def)
     75   {
     76     m_elemDef = def;
     77   }
     78 
     79   /**
     80    * Resolve an external entity.
     81    *
     82    *
     83    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
     84    * @param publicId The public identifer, or null if none is
     85    *                 available.
     86    * @param systemId The system identifier provided in the XML
     87    *                 document.
     88    * @return The new input source, or null to require the
     89    *         default behaviour.
     90    */
     91   public InputSource resolveEntity(
     92           StylesheetHandler handler, String publicId, String systemId)
     93             throws org.xml.sax.SAXException
     94   {
     95     return null;
     96   }
     97 
     98   /**
     99    * Receive notification of a notation declaration.
    100    *
    101    *
    102    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    103    * @param name The notation name.
    104    * @param publicId The notation public identifier, or null if not
    105    *                 available.
    106    * @param systemId The notation system identifier.
    107    * @see org.xml.sax.DTDHandler#notationDecl
    108    */
    109   public void notationDecl(StylesheetHandler handler, String name,
    110                            String publicId, String systemId)
    111   {
    112 
    113     // no op
    114   }
    115 
    116   /**
    117    * Receive notification of an unparsed entity declaration.
    118    *
    119    *
    120    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    121    * @param name The entity name.
    122    * @param publicId The entity public identifier, or null if not
    123    *                 available.
    124    * @param systemId The entity system identifier.
    125    * @param notationName The name of the associated notation.
    126    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
    127    */
    128   public void unparsedEntityDecl(StylesheetHandler handler, String name,
    129                                  String publicId, String systemId,
    130                                  String notationName)
    131   {
    132 
    133     // no op
    134   }
    135 
    136   /**
    137    * Receive notification of the start of the non-text event.  This
    138    * is sent to the current processor when any non-text event occurs.
    139    *
    140    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    141    */
    142   public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException
    143   {
    144 
    145     // no op
    146   }
    147 
    148   /**
    149    * Receive notification of the start of an element.
    150    *
    151    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    152    * @param uri The Namespace URI, or an empty string.
    153    * @param localName The local name (without prefix), or empty string if not namespace processing.
    154    * @param rawName The qualified name (with prefix).
    155    * @param attributes The specified or defaulted attributes.
    156    */
    157   public void startElement(
    158           StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
    159             throws org.xml.sax.SAXException
    160   {
    161 
    162     if (m_savedLastOrder == null)
    163 				m_savedLastOrder = new IntStack();
    164 			m_savedLastOrder.push(getElemDef().getLastOrder());
    165 			getElemDef().setLastOrder(-1);
    166   }
    167 
    168   /**
    169    * Receive notification of the end of an element.
    170    *
    171    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    172    * @param uri The Namespace URI, or an empty string.
    173    * @param localName The local name (without prefix), or empty string if not namespace processing.
    174    * @param rawName The qualified name (with prefix).
    175    */
    176   public void endElement(
    177           StylesheetHandler handler, String uri, String localName, String rawName)
    178             throws org.xml.sax.SAXException
    179   {
    180 		if (m_savedLastOrder != null && !m_savedLastOrder.empty())
    181 			getElemDef().setLastOrder(m_savedLastOrder.pop());
    182 
    183 		if (!getElemDef().getRequiredFound())
    184 			handler.error(XSLTErrorResources.ER_REQUIRED_ELEM_NOT_FOUND, new Object[]{getElemDef().getRequiredElem()}, null);
    185   }
    186 
    187   /**
    188    * Receive notification of character data inside an element.
    189    *
    190    *
    191    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    192    * @param ch The characters.
    193    * @param start The start position in the character array.
    194    * @param length The number of characters to use from the
    195    *               character array.
    196    */
    197   public void characters(
    198           StylesheetHandler handler, char ch[], int start, int length)
    199             throws org.xml.sax.SAXException
    200   {
    201     handler.error(XSLTErrorResources.ER_CHARS_NOT_ALLOWED, null, null);//"Characters are not allowed at this point in the document!",
    202                   //null);
    203   }
    204 
    205   /**
    206    * Receive notification of ignorable whitespace in element content.
    207    *
    208    *
    209    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    210    * @param ch The whitespace characters.
    211    * @param start The start position in the character array.
    212    * @param length The number of characters to use from the
    213    *               character array.
    214    */
    215   public void ignorableWhitespace(
    216           StylesheetHandler handler, char ch[], int start, int length)
    217             throws org.xml.sax.SAXException
    218   {
    219 
    220     // no op
    221   }
    222 
    223   /**
    224    * Receive notification of a processing instruction.
    225    *
    226    *
    227    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    228    * @param target The processing instruction target.
    229    * @param data The processing instruction data, or null if
    230    *             none is supplied.
    231    */
    232   public void processingInstruction(
    233           StylesheetHandler handler, String target, String data)
    234             throws org.xml.sax.SAXException
    235   {
    236 
    237     // no op
    238   }
    239 
    240   /**
    241    * Receive notification of a skipped entity.
    242    *
    243    *
    244    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    245    * @param name The name of the skipped entity.
    246    */
    247   public void skippedEntity(StylesheetHandler handler, String name)
    248           throws org.xml.sax.SAXException
    249   {
    250 
    251     // no op
    252   }
    253 
    254   /**
    255    * Set the properties of an object from the given attribute list.
    256    * @param handler The stylesheet's Content handler, needed for
    257    *                error reporting.
    258    * @param rawName The raw name of the owner element, needed for
    259    *                error reporting.
    260    * @param attributes The list of attributes.
    261    * @param target The target element where the properties will be set.
    262    */
    263   void setPropertiesFromAttributes(
    264           StylesheetHandler handler, String rawName, Attributes attributes,
    265           ElemTemplateElement target)
    266             throws org.xml.sax.SAXException
    267   {
    268     setPropertiesFromAttributes(handler, rawName, attributes, target, true);
    269   }
    270 
    271   /**
    272    * Set the properties of an object from the given attribute list.
    273    * @param handler The stylesheet's Content handler, needed for
    274    *                error reporting.
    275    * @param rawName The raw name of the owner element, needed for
    276    *                error reporting.
    277    * @param attributes The list of attributes.
    278    * @param target The target element where the properties will be set.
    279    * @param throwError True if it should throw an error if an
    280    * attribute is not defined.
    281    * @return the attributes not allowed on this element.
    282    *
    283    * @throws TransformerException
    284    */
    285   Attributes setPropertiesFromAttributes(
    286           StylesheetHandler handler, String rawName, Attributes attributes,
    287           ElemTemplateElement target, boolean throwError)
    288             throws org.xml.sax.SAXException
    289   {
    290 
    291     XSLTElementDef def = getElemDef();
    292     AttributesImpl undefines = null;
    293     boolean isCompatibleMode = ((null != handler.getStylesheet()
    294                                  && handler.getStylesheet().getCompatibleMode())
    295                                 || !throwError);
    296     if (isCompatibleMode)
    297       undefines = new AttributesImpl();
    298 
    299 
    300     // Keep track of which XSLTAttributeDefs have been processed, so
    301     // I can see which default values need to be set.
    302     List processedDefs = new ArrayList();
    303 
    304     // Keep track of XSLTAttributeDefs that were invalid
    305     List errorDefs = new ArrayList();
    306     int nAttrs = attributes.getLength();
    307 
    308     for (int i = 0; i < nAttrs; i++)
    309     {
    310       String attrUri = attributes.getURI(i);
    311       // Hack for Crimson.  -sb
    312       if((null != attrUri) && (attrUri.length() == 0)
    313                            && (attributes.getQName(i).startsWith("xmlns:") ||
    314                                attributes.getQName(i).equals("xmlns")))
    315       {
    316         attrUri = org.apache.xalan.templates.Constants.S_XMLNAMESPACEURI;
    317       }
    318       String attrLocalName = attributes.getLocalName(i);
    319       XSLTAttributeDef attrDef = def.getAttributeDef(attrUri, attrLocalName);
    320 
    321       if (null == attrDef)
    322       {
    323         if (!isCompatibleMode)
    324         {
    325 
    326           // Then barf, because this element does not allow this attribute.
    327           handler.error(XSLTErrorResources.ER_ATTR_NOT_ALLOWED, new Object[]{attributes.getQName(i), rawName}, null);//"\""+attributes.getQName(i)+"\""
    328                         //+ " attribute is not allowed on the " + rawName
    329                        // + " element!", null);
    330         }
    331         else
    332         {
    333           undefines.addAttribute(attrUri, attrLocalName,
    334                                  attributes.getQName(i),
    335                                  attributes.getType(i),
    336                                  attributes.getValue(i));
    337         }
    338       }
    339       else
    340       {
    341         // Can we switch the order here:
    342 
    343         boolean success = attrDef.setAttrValue(handler, attrUri, attrLocalName,
    344                              attributes.getQName(i), attributes.getValue(i),
    345                              target);
    346 
    347         // Now we only add the element if it passed a validation check
    348         if (success)
    349             processedDefs.add(attrDef);
    350         else
    351             errorDefs.add(attrDef);
    352       }
    353     }
    354 
    355     XSLTAttributeDef[] attrDefs = def.getAttributes();
    356     int nAttrDefs = attrDefs.length;
    357 
    358     for (int i = 0; i < nAttrDefs; i++)
    359     {
    360       XSLTAttributeDef attrDef = attrDefs[i];
    361       String defVal = attrDef.getDefault();
    362 
    363       if (null != defVal)
    364       {
    365         if (!processedDefs.contains(attrDef))
    366         {
    367           attrDef.setDefAttrValue(handler, target);
    368         }
    369       }
    370 
    371       if (attrDef.getRequired())
    372       {
    373         if ((!processedDefs.contains(attrDef)) && (!errorDefs.contains(attrDef)))
    374           handler.error(
    375             XSLMessages.createMessage(
    376               XSLTErrorResources.ER_REQUIRES_ATTRIB, new Object[]{ rawName,
    377                                                                    attrDef.getName() }), null);
    378       }
    379     }
    380 
    381     return undefines;
    382   }
    383 }
    384