You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mi...@apache.org on 2005/02/11 07:18:14 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/serialize SerializerUtils.java

minchau     2005/02/10 22:18:14

  Modified:    java/src/org/apache/xml/serializer ToUnknownStream.java
                        EmptySerializer.java ToTextStream.java
                        ToXMLSAXHandler.java AttributesImplSerializer.java
                        ToXMLStream.java NamespaceMappings.java
                        ExtendedContentHandler.java ToTextSAXHandler.java
                        ToStream.java SerializerBase.java
               java/src/org/apache/xalan/templates ElemAttribute.java
                        ElemLiteralResult.java
               java/src/org/apache/xalan/serialize SerializerUtils.java
  Log:
  Fix for XALANJ-1886. Multiple problems fixed related to collecting xsl:attributes 
  with over-ridden values and prefix/URI maps.  With this fix, internally the
  serializer correctly identifies attributes by their expanded QName, which 
  includes the URI rather than the prefix.
  
  Revision  Changes    Path
  1.11      +5 -3      xml-xalan/java/src/org/apache/xml/serializer/ToUnknownStream.java
  
  Index: ToUnknownStream.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToUnknownStream.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ToUnknownStream.java	23 Jan 2005 00:52:41 -0000	1.10
  +++ ToUnknownStream.java	11 Feb 2005 06:18:13 -0000	1.11
  @@ -258,6 +258,7 @@
        * @param rawName the attribute name, with prefix (if any)
        * @param type the type of the attribute, typically "CDATA"
        * @param value the value of the parameter
  +     * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
        * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
        */
       public void addAttribute(
  @@ -265,14 +266,15 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
           throws SAXException
       {
           if (m_firstTagNotEmitted)
           {
               flush();
           }
  -        m_handler.addAttribute(uri, localName, rawName, type, value);
  +        m_handler.addAttribute(uri, localName, rawName, type, value, XSLAttribute);
       }
       /**
        * Adds an attribute to the currenly open tag
  
  
  
  1.8       +11 -2     xml-xalan/java/src/org/apache/xml/serializer/EmptySerializer.java
  
  Index: EmptySerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/EmptySerializer.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- EmptySerializer.java	14 Oct 2004 21:45:05 -0000	1.7
  +++ EmptySerializer.java	11 Feb 2005 06:18:13 -0000	1.8
  @@ -232,7 +232,8 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)        
           throws SAXException
       {
           couldThrowSAXException();
  @@ -708,4 +709,12 @@
       {
           couldThrowSAXException();        
       }
  +    
  +    /**
  +     * @see org.apache.xml.serializer.ExtendedContentHandler#addXSLAttribute(java.lang.String, java.lang.String, java.lang.String)
  +     */
  +    public void addXSLAttribute(String qName, String value, String uri)
  +    {
  +        aMethodIsCalled();        
  +    }
   }
  
  
  
  1.20      +3 -2      xml-xalan/java/src/org/apache/xml/serializer/ToTextStream.java
  
  Index: ToTextStream.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToTextStream.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- ToTextStream.java	23 Jan 2005 00:52:41 -0000	1.19
  +++ ToTextStream.java	11 Feb 2005 06:18:13 -0000	1.20
  @@ -583,7 +583,8 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
       {
           // do nothing, just forget all about the attribute
       }
  
  
  
  1.16      +15 -13    xml-xalan/java/src/org/apache/xml/serializer/ToXMLSAXHandler.java
  
  Index: ToXMLSAXHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToXMLSAXHandler.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- ToXMLSAXHandler.java	14 Oct 2004 21:45:05 -0000	1.15
  +++ ToXMLSAXHandler.java	11 Feb 2005 06:18:13 -0000	1.16
  @@ -363,7 +363,7 @@
               if (getShouldOutputNSAttr()) 
               {
   
  -	              /* bjm: don't know if we really needto do this. The
  +	              /* Brian M.: don't know if we really needto do this. The
   	               * callers of this object should have injected both
   	               * startPrefixMapping and the attributes.  We are
   	               * just covering our butt here.
  @@ -372,7 +372,7 @@
     	            if (EMPTYSTRING.equals(prefix))
     	            {
     	                name = "xmlns";
  -  	                addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
  +  	                addAttributeAlways(XMLNS_URI, name, name,"CDATA",uri, false);
     	            }
     	            else 
                   {
  @@ -384,7 +384,7 @@
     	             	 	     *  the uri is the value, that is why we pass it in the
     	             	 	     * value, or 5th slot of addAttributeAlways()
     	                 	   */
  -  	                    addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri);
  +  	                    addAttributeAlways(XMLNS_URI, prefix, name,"CDATA",uri, false );
     	                }
     	            }
               }
  @@ -684,10 +684,9 @@
           if (ns != null && ns.length() > 0)
           {
               int index;
  -            String prefix =
  -                (index = rawName.indexOf(":")) < 0
  -                    ? ""
  -                    : rawName.substring(0, index);
  +            final boolean no_prefix = ((index = rawName.indexOf(":")) < 0);
  +            String prefix = (no_prefix) ? "" : rawName.substring(0, index);
  +
   
               if (null != prefix)
               {
  @@ -702,10 +701,11 @@
                           // SAX does expect both.
                           this.addAttributeAlways(
                               "http://www.w3.org/2000/xmlns/",
  -                            prefix,
  -                            "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
  +                            no_prefix ? "xmlns" : prefix,  // local name
  +                            no_prefix ? "xmlns" : ("xmlns:"+ prefix), // qname
                               "CDATA",
  -                            ns);
  +                            ns,
  +                            false);
                       }
                   }
   
  @@ -722,6 +722,7 @@
        * @param rawName    the qualified name of the attribute
        * @param type the type of the attribute (probably CDATA)
        * @param value the value of the attribute
  +     * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
        * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
        */
       public void addAttribute(
  @@ -729,13 +730,14 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
           throws SAXException
       {      
           if (m_elemContext.m_startTagOpen)
           {
               ensurePrefixIsDeclared(uri, rawName);
  -            addAttributeAlways(uri, localName, rawName, type, value);
  +            addAttributeAlways(uri, localName, rawName, type, value, false);
           }
   
       } 
  
  
  
  1.6       +60 -8     xml-xalan/java/src/org/apache/xml/serializer/AttributesImplSerializer.java
  
  Index: AttributesImplSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/AttributesImplSerializer.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- AttributesImplSerializer.java	14 Oct 2004 21:45:05 -0000	1.5
  +++ AttributesImplSerializer.java	11 Feb 2005 06:18:13 -0000	1.6
  @@ -34,18 +34,23 @@
    * 
    * @xsl.usage internal
    */
  -final class AttributesImplSerializer extends AttributesImpl
  +public final class AttributesImplSerializer extends AttributesImpl
   {
       /**
        * Hash table of qName/index values to quickly lookup the index
        * of an attributes qName.  qNames are in uppercase in the hash table
        * to make the search case insensitive.
  +     * 
  +     * The keys to the hashtable to find the index are either
  +     * "prefix:localName"  or "{uri}localName".
        */
  -    private Hashtable m_indexFromQName = new Hashtable();
  +    private final Hashtable m_indexFromQName = new Hashtable();
  +    
  +    private final StringBuffer m_buff = new StringBuffer();
       
       /**
        * This is the number of attributes before switching to the hash table,
  -     * and can be tuned, but 12 seems good for now - bjm
  +     * and can be tuned, but 12 seems good for now - Brian M.
        */
       private static final int MAX = 12;
       
  @@ -61,7 +66,7 @@
        * @return the integer index of the attribute.
        * @see org.xml.sax.Attributes#getIndex(String)
        */
  -    public int getIndex(String qname)
  +    public final int getIndex(String qname)
       {
           int index;
   
  @@ -93,7 +98,7 @@
        * @see org.xml.sax.helpers.AttributesImpl#addAttribute(String, String, String, String, String)
        * @see #getIndex(String)
        */
  -    public void addAttribute(
  +    public final void addAttribute(
           String uri,
           String local,
           String qname,
  @@ -115,9 +120,16 @@
           }
           else
           {
  +            /* add the key with the format of "prefix:localName" */
               /* we have just added the attibute, its index is the old length */
               Integer i = new Integer(index);
               m_indexFromQName.put(qname, i);
  +            
  +            /* now add with key of the format "{uri}localName" */
  +            m_buff.setLength(0);
  +            m_buff.append('{').append(uri).append('}').append(local);
  +            String key = m_buff.toString();
  +            m_indexFromQName.put(key, i);
           }
           return;
       }
  @@ -137,6 +149,14 @@
               String qName = super.getQName(index);
               Integer i = new Integer(index);
               m_indexFromQName.put(qName, i);
  +            
  +            // Add quick look-up to find with uri/local name pair
  +            String uri = super.getURI(index);
  +            String local = super.getLocalName(index);
  +            m_buff.setLength(0);
  +            m_buff.append('{').append(uri).append('}').append(local);
  +            String key = m_buff.toString();
  +            m_indexFromQName.put(key, i);
           }
       }
   
  @@ -145,7 +165,7 @@
        *
        * @see org.xml.sax.helpers.AttributesImpl#clear()
        */
  -    public void clear()
  +    public final void clear()
       {
   
           int len = super.getLength();
  @@ -167,7 +187,7 @@
        * @see org.xml.sax.helpers.AttributesImpl#setAttributes(Attributes)
        * @see #getIndex(String)
        */
  -    public void setAttributes(Attributes atts)
  +    public final void setAttributes(Attributes atts)
       {
   
           super.setAttributes(atts);
  @@ -180,4 +200,36 @@
               switchOverToHash(numAtts);
   
       }
  +    
  +    /**
  +     * This method gets the index of an attribute given its uri and locanName.
  +     * @param uri the URI of the attribute name.
  +     * @param localName the local namer (after the ':' ) of the attribute name.
  +     * @return the integer index of the attribute.
  +     * @see org.xml.sax.Attributes#getIndex(String)
  +     */
  +    public final int getIndex(String uri, String localName)
  +    {
  +        int index;
  +
  +        if (super.getLength() < MAX)
  +        {
  +            // if we haven't got too many attributes let the
  +            // super class look it up
  +            index = super.getIndex(uri,localName);
  +            return index;
  +        }
  +        // we have too many attributes and the super class is slow
  +        // so find it quickly using our Hashtable.
  +        // Form the key of format "{uri}localName"
  +        m_buff.setLength(0);
  +        m_buff.append('{').append(uri).append('}').append(localName);
  +        String key = m_buff.toString();
  +        Integer i = (Integer)m_indexFromQName.get(key);
  +        if (i == null)
  +            index = -1;
  +        else
  +            index = i.intValue();
  +        return index;
  +    }
   }
  
  
  
  1.18      +26 -4     xml-xalan/java/src/org/apache/xml/serializer/ToXMLStream.java
  
  Index: ToXMLStream.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToXMLStream.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- ToXMLStream.java	16 Dec 2004 19:24:09 -0000	1.17
  +++ ToXMLStream.java	11 Feb 2005 06:18:13 -0000	1.18
  @@ -404,17 +404,39 @@
           }
       }
   
  +    /**
  +     * Add an attribute to the current element.
  +     * @param uri the URI associated with the element name
  +     * @param localName local part of the attribute name
  +     * @param rawName   prefix:localName
  +     * @param type
  +     * @param value the value of the attribute
  +     * @param xslAttribute true if this attribute is from an xsl:attribute,
  +     * false if declared within the elements opening tag.
  +     * @throws SAXException
  +     */
       public void addAttribute(
           String uri,
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean xslAttribute)
           throws SAXException
       {
           if (m_elemContext.m_startTagOpen)
           {
  -            if (!rawName.startsWith("xmlns"))
  +            boolean was_added = addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
  +            
  +
  +            /*
  +             * We don't run this block of code if:
  +             * 1. The attribute value was only replaced (was_added is false).
  +             * 2. The attribute is from an xsl:attribute element (that is handled
  +             *    in the addAttributeAlways() call just above.
  +             * 3. The name starts with "xmlns", i.e. it is a namespace declaration.
  +             */
  +            if (was_added && !xslAttribute && !rawName.startsWith("xmlns"))
               {
                   String prefixUsed =
                       ensureAttributesNamespaceIsDeclared(
  @@ -431,7 +453,7 @@
   
                   }
               }
  -            addAttributeAlways(uri, localName, rawName, type, value);
  +            addAttributeAlways(uri, localName, rawName, type, value, xslAttribute);
           }
           else
           {
  
  
  
  1.8       +55 -32    xml-xalan/java/src/org/apache/xml/serializer/NamespaceMappings.java
  
  Index: NamespaceMappings.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/NamespaceMappings.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- NamespaceMappings.java	14 Oct 2004 21:45:05 -0000	1.7
  +++ NamespaceMappings.java	11 Feb 2005 06:18:13 -0000	1.8
  @@ -69,27 +69,17 @@
       private int count = 0;
   
       /**
  -     * Stack of prefixes that have mappings
  -     * The top of this stack is the prefix that was last mapped to an URI
  -     * 
  -     * For every prefix pushed on this stack a corresponding integer is pushed
  -     * on the m_nodeStack. That way all prefixes pushed at the current depth can
  -     * be removed at the same time.      
  -     */
  -    private java.util.Stack m_prefixStack = new Stack();
  -
  -    /**
        * Each entry (prefix) in this hashtable points to a Stack of URIs
        */
       private Hashtable m_namespaces = new Hashtable();
   
       /** 
  -     * The top of this stack contains the nested element depth
  +     * The top of this stack contains the MapRecord
        * of the last declared a namespace.
        * Used to know how many prefix mappings to pop when leaving
        * the current element depth.
        * For every prefix mapping the current element depth is 
  -     * pushed on this stack, as well as the prefix on the m_prefixStack
  +     * pushed on this stack.
        * That way all prefixes pushed at the current depth can be 
        * removed at the same time.
        * Used to ensure prefix/uri map scopes are closed correctly
  @@ -120,14 +110,13 @@
           // Define the default namespace (initially maps to "" uri)
           Stack stack;
           m_namespaces.put(EMPTYSTRING, stack = new Stack());
  -        stack.push(EMPTYSTRING);
  -        m_prefixStack.push(EMPTYSTRING);
  +        stack.push(new MappingRecord(EMPTYSTRING,EMPTYSTRING,0));
   
           m_namespaces.put(XML_PREFIX, stack = new Stack());
  -        stack.push("http://www.w3.org/XML/1998/namespace");
  -        m_prefixStack.push(XML_PREFIX);
  +        stack.push(new MappingRecord( XML_PREFIX,
  +            "http://www.w3.org/XML/1998/namespace",0));
   
  -        m_nodeStack.push(new Integer(-1));
  +        m_nodeStack.push(new MappingRecord(null,null,-1));
   
       }
   
  @@ -140,7 +129,14 @@
       public String lookupNamespace(String prefix)
       {
           final Stack stack = (Stack) m_namespaces.get(prefix);
  -        return stack != null && !stack.isEmpty() ? (String) stack.peek() : null;
  +        return stack != null && !stack.isEmpty() ? 
  +            ((MappingRecord) stack.peek()).m_uri : null;
  +    }
  +    
  +    MappingRecord getMappingFromPrefix(String prefix) {
  +        final Stack stack = (Stack) m_namespaces.get(prefix);
  +        return stack != null && !stack.isEmpty() ? 
  +            ((MappingRecord) stack.peek()) : null;
       }
   
       /**
  @@ -167,6 +163,23 @@
           }
           return foundPrefix;
       }
  +    
  +    MappingRecord getMappingFromURI(String uri)
  +    {
  +        MappingRecord foundMap = null;
  +        Enumeration prefixes = m_namespaces.keys();
  +        while (prefixes.hasMoreElements())
  +        {
  +            String prefix = (String) prefixes.nextElement();
  +            MappingRecord map2 = getMappingFromPrefix(prefix);
  +            if (map2 != null && (map2.m_uri).equals(uri))
  +            {
  +                foundMap = map2;
  +                break;
  +            }
  +        }
  +        return foundMap;
  +    }
   
       /**
        * Undeclare the namespace that is currently pointed to by a given prefix
  @@ -209,14 +222,13 @@
               m_namespaces.put(prefix, stack = new Stack());
           }
   
  -        if (!stack.empty() && uri.equals(stack.peek()))
  +        if (!stack.empty() && uri.equals(((MappingRecord)stack.peek()).m_uri))
           {
               return false;
           }
  -
  -        stack.push(uri);
  -        m_prefixStack.push(prefix);
  -        m_nodeStack.push(new Integer(elemDepth));
  +        MappingRecord map = new MappingRecord(prefix,uri,elemDepth);
  +        stack.push(map);
  +        m_nodeStack.push(map);
           return true;
       }
   
  @@ -234,15 +246,16 @@
           {
               if (m_nodeStack.isEmpty())
                   return;
  -            Integer i = (Integer) (m_nodeStack.peek());
  -            if (i.intValue() < elemDepth)
  +            MappingRecord map = (MappingRecord)(m_nodeStack.peek());
  +            int depth = map.m_delarationDepth;
  +            if (depth < elemDepth)
                   return;
               /* the depth of the declared mapping is elemDepth or deeper
                * so get rid of it
                */
   
  -            m_nodeStack.pop();
  -            final String prefix = (String) m_prefixStack.pop(); 
  +            map = (MappingRecord) m_nodeStack.pop();
  +            final String prefix = map.m_prefix; 
               popNamespace(prefix);
               if (saxHandler != null)
               {
  @@ -275,7 +288,6 @@
        */
       public Object clone() throws CloneNotSupportedException {
           NamespaceMappings clone = new NamespaceMappings();
  -        clone.m_prefixStack = (Stack)m_prefixStack.clone();
           clone.m_nodeStack = (Stack) m_nodeStack.clone();
           clone.m_namespaces = (Hashtable) m_namespaces.clone();
           
  @@ -288,10 +300,21 @@
       {
           this.count = 0;
           this.m_namespaces.clear();
  -        this.m_nodeStack.clear();
  -        this.m_prefixStack.clear();
  -        
  +        this.m_nodeStack.clear();        
           initNamespaces();
       }
  +    
  +    class MappingRecord {
  +        final String m_prefix;  // the prefix
  +        final String m_uri;     // the uri
  +        // the depth of the element where declartion was made
  +        final int m_delarationDepth;
  +        MappingRecord(String prefix, String uri, int depth) {
  +            m_prefix = prefix;
  +            m_uri = uri;
  +            m_delarationDepth = depth;
  +            
  +        }
  +    }
   
   }
  
  
  
  1.6       +12 -2     xml-xalan/java/src/org/apache/xml/serializer/ExtendedContentHandler.java
  
  Index: ExtendedContentHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ExtendedContentHandler.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ExtendedContentHandler.java	14 Oct 2004 21:45:05 -0000	1.5
  +++ ExtendedContentHandler.java	11 Feb 2005 06:18:13 -0000	1.6
  @@ -51,6 +51,7 @@
        * @param rawName the qualified name of the attribute
        * @param type the attribute type typically character data (CDATA)
        * @param value the value of the attribute
  +     * @param XSLAttribute true if the added attribute is coming from an xsl:attribute element
        * @throws SAXException
        */
       public void addAttribute(
  @@ -58,7 +59,8 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
           throws SAXException;
       /**
        * Add attributes to the current element
  @@ -238,4 +240,12 @@
        */
       public void addUniqueAttribute(String qName, String value, int flags)
           throws SAXException;
  +    
  +    /**
  +     * Add an attribute from an xsl:attribute element.
  +     * @param qName the qualified attribute name (prefix:localName)
  +     * @param value the attributes value
  +     * @param uri the uri that the prefix of the qName is mapped to.
  +     */    
  +    public void addXSLAttribute(String qName, final String value, final String uri);
   }
  
  
  
  1.7       +3 -2      xml-xalan/java/src/org/apache/xml/serializer/ToTextSAXHandler.java
  
  Index: ToTextSAXHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToTextSAXHandler.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ToTextSAXHandler.java	14 Oct 2004 21:45:05 -0000	1.6
  +++ ToTextSAXHandler.java	11 Feb 2005 06:18:13 -0000	1.7
  @@ -183,7 +183,8 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
       {
       }
   
  
  
  
  1.38      +108 -21   xml-xalan/java/src/org/apache/xml/serializer/ToStream.java
  
  Index: ToStream.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/ToStream.java,v
  retrieving revision 1.37
  retrieving revision 1.38
  diff -u -r1.37 -r1.38
  --- ToStream.java	23 Jan 2005 00:52:41 -0000	1.37
  +++ ToStream.java	11 Feb 2005 06:18:13 -0000	1.38
  @@ -1841,7 +1841,7 @@
               if (dothis)
               {
                   // at one point this code seemed right,
  -                // but not anymore - bjm
  +                // but not anymore - Brian M.
                   if (closeDecl)
                   {
                       writer.write('>');
  @@ -2100,7 +2100,7 @@
   
           if (pushed)
           {
  -            /* bjm: don't know if we really needto do this. The
  +            /* Brian M.: don't know if we really needto do this. The
                * callers of this object should have injected both
                * startPrefixMapping and the attributes.  We are 
                * just covering our butt here.
  @@ -2109,7 +2109,7 @@
               if (EMPTYSTRING.equals(prefix))
               {
                   name = "xmlns";
  -                addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
  +                addAttributeAlways(XMLNS_URI, name, name, "CDATA", uri, false);
               }
               else
               {
  @@ -2122,7 +2122,7 @@
                        *  the      uri is the value, that is why we pass it in the
                        * value, or 5th slot of addAttributeAlways()
                        */
  -                    addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri);
  +                    addAttributeAlways(XMLNS_URI, prefix, name, "CDATA", uri, false);
                   }
               }
           }
  @@ -2586,7 +2586,7 @@
                           prefixFromRawName,
                           "xmlns:" + prefixFromRawName,
                           "CDATA",
  -                        ns);
  +                        ns, false);
                       return prefixFromRawName;
                   }
               }
  @@ -2606,7 +2606,7 @@
                           prefix,
                           "xmlns:" + prefix,
                           "CDATA",
  -                        ns);
  +                        ns, false);
                   }
   
                   return prefix;
  @@ -2623,10 +2623,8 @@
           if (ns != null && ns.length() > 0)
           {
               int index;
  -            String prefix =
  -                (index = rawName.indexOf(":")) < 0
  -                    ? ""
  -                    : rawName.substring(0, index);
  +            final boolean no_prefix = ((index = rawName.indexOf(":")) < 0);
  +            String prefix = (no_prefix) ? "" : rawName.substring(0, index);
   
               if (null != prefix)
               {
  @@ -2641,10 +2639,11 @@
   
                       this.addAttributeAlways(
                           "http://www.w3.org/2000/xmlns/",
  -                        prefix,
  -                        "xmlns" + (prefix.length() == 0 ? "" : ":") + prefix,
  +                        no_prefix ? "xmlns" : prefix,  // local name
  +                        no_prefix ? "xmlns" : ("xmlns:"+ prefix), // qname
                           "CDATA",
  -                        ns);
  +                        ns,
  +                        false);
                   }
   
               }
  @@ -2684,7 +2683,7 @@
   
       /**
        * Adds the given attribute to the set of attributes, even if there is
  -     * nocurrently open element. This is useful if a SAX startPrefixMapping()
  +     * no currently open element. This is useful if a SAX startPrefixMapping()
        * should need to add an attribute before the element name is seen.
        * 
        * This method is a copy of its super classes method, except that some
  @@ -2696,17 +2695,27 @@
        * @param rawName   the qualified name of the attribute
        * @param type the type of the attribute (probably CDATA)
        * @param value the value of the attribute
  +     * @param xslAttribute true if this attribute is coming from an xsl:attribute element.
  +     * @return true if the attribute value was added, 
  +     * false if the attribute already existed and the value was
  +     * replaced with the new value.
        */
  -    public void addAttributeAlways(
  +    public boolean addAttributeAlways(
           String uri,
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean xslAttribute)
       {
  -
  +        boolean was_added;
           int index;
  -        index = m_attributes.getIndex(rawName);
  +        if (uri == null || localName == null || uri.length() == 0)
  +            index = m_attributes.getIndex(rawName);
  +        else {
  +            index = m_attributes.getIndex(uri, localName);
  +        }
  +
           if (index >= 0)
           {
               String old_value = null;
  @@ -2722,6 +2731,7 @@
                * want to re-set is the value anyway.
                */
               m_attributes.setValue(index, value);
  +            was_added = false;
               if (old_value != null)
                   firePseudoAttributes();
   
  @@ -2729,11 +2739,88 @@
           else
           {
               // the attribute doesn't exist yet, create it
  +            if (xslAttribute)
  +            {
  +                /*
  +                 * This attribute is from an xsl:attribute element so we take some care in
  +                 * adding it, e.g.
  +                 *   <elem1  foo:attr1="1" xmlns:foo="uri1">
  +                 *       <xsl:attribute name="foo:attr2">2</xsl:attribute>
  +                 *   </elem1>
  +                 * 
  +                 * We are adding attr1 and attr2 both as attributes of elem1,
  +                 * and this code is adding attr2 (the xsl:attribute ).
  +                 * We could have a collision with the prefix like in the example above.
  +                 */
  +
  +                // In the example above, is there a prefix like foo ?
  +                final int colonIndex = rawName.indexOf(':');
  +                if (colonIndex > 0)
  +                {
  +                    String prefix = rawName.substring(0,colonIndex);
  +                    NamespaceMappings.MappingRecord existing_mapping = m_prefixMap.getMappingFromPrefix(prefix);
  +
  +                    /* Before adding this attribute (foo:attr2),
  +                     * is the prefix for it (foo) already mapped at the current depth?
  +                     */
  +                    if (existing_mapping != null 
  +                    && existing_mapping.m_delarationDepth == m_elemContext.m_currentElemDepth
  +                    && !existing_mapping.m_uri.equals(uri))
  +                    {
  +                        /*
  +                         * There is an existing mapping of this prefix,
  +                         * it differs from the one we need,
  +                         * and unfortunately it is at the current depth so we 
  +                         * can not over-ride it.
  +                         */
  +
  +                        /*
  +                         * Are we lucky enough that an existing other prefix maps to this URI ?
  +                         */
  +                        prefix = m_prefixMap.lookupPrefix(uri);
  +                        if (prefix == null)
  +                        {
  +                            /* Unfortunately there is no existing prefix that happens to map to ours,
  +                             * so to avoid a prefix collision we must generated a new prefix to use. 
  +                             * This is OK because the prefix URI mapping
  +                             * defined in the xsl:attribute is short in scope, 
  +                             * just the xsl:attribute element itself, 
  +                             * and at this point in serialization the body of the
  +                             * xsl:attribute, if any, is just a String. Right?
  +                             *   . . . I sure hope so - Brian M. 
  +                             */
  +                            prefix = m_prefixMap.generateNextPrefix();
  +                        }
  +
  +                        rawName = prefix + ':' + localName;
  +                    }
  +                }
  +
  +                try
  +                {
  +                    /* This is our last chance to make sure the namespace for this
  +                     * attribute is declared, especially if we just generated an alternate
  +                     * prefix to avoid a collision (the new prefix/rawName will go out of scope
  +                     * soon and be lost ...  last chance here.
  +                     */
  +                    String prefixUsed =
  +                        ensureAttributesNamespaceIsDeclared(
  +                            uri,
  +                            localName,
  +                            rawName);
  +                }
  +                catch (SAXException e)
  +                {
  +                    // TODO Auto-generated catch block
  +                    e.printStackTrace();
  +                }
  +            }
               m_attributes.addAttribute(uri, localName, rawName, type, value);
  +            was_added = true;
               if (m_tracer != null)
                   firePseudoAttributes();
           }
  -
  +        return was_added;
       }
   
       /**
  @@ -2881,7 +2968,7 @@
            this.m_disableOutputEscapingStates.clear();
            
            this.m_escaping = true;
  -         // Leave m_format alone for now - bjm
  +         // Leave m_format alone for now - Brian M.
            // this.m_format = null;
            this.m_inDoctype = false;
            this.m_ispreserve = false;
  
  
  
  1.17      +42 -8     xml-xalan/java/src/org/apache/xml/serializer/SerializerBase.java
  
  Index: SerializerBase.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/serializer/SerializerBase.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- SerializerBase.java	24 Jan 2005 04:04:40 -0000	1.16
  +++ SerializerBase.java	11 Feb 2005 06:18:13 -0000	1.17
  @@ -323,6 +323,7 @@
        * @param rawName    the qualified name of the attribute
        * @param type the type of the attribute (probably CDATA)
        * @param value the value of the attribute
  +     * @param XSLAttribute true if this attribute is coming from an xsl:attriute element
        * @see org.apache.xml.serializer.ExtendedContentHandler#addAttribute(String, String, String, String, String)
        */
       public void addAttribute(
  @@ -330,12 +331,13 @@
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
           throws SAXException
       {
           if (m_elemContext.m_startTagOpen)
           {
  -            addAttributeAlways(uri, localName, rawName, type, value);
  +            addAttributeAlways(uri, localName, rawName, type, value, XSLAttribute);
           }
   
       }
  @@ -350,14 +352,19 @@
        * @param rawName   the qualified name of the attribute
        * @param type the type of the attribute (probably CDATA)
        * @param value the value of the attribute
  +     * @param XSLAttribute true if this attribute is coming from an xsl:attribute element
  +     * @return true if the attribute was added, 
  +     * false if an existing value was replaced.
        */
  -    public void addAttributeAlways(
  +    public boolean addAttributeAlways(
           String uri,
           String localName,
           String rawName,
           String type,
  -        String value)
  +        String value,
  +        boolean XSLAttribute)
       {
  +        boolean was_added;
   //            final int index =
   //                (localName == null || uri == null) ?
   //                m_attributes.getIndex(rawName):m_attributes.getIndex(uri, localName);        
  @@ -368,7 +375,11 @@
   //            else {
   //                index = m_attributes.getIndex(uri, localName);
   //            }
  -            index = m_attributes.getIndex(rawName);
  +            if (localName == null || uri == null || uri.length() == 0)
  +                index = m_attributes.getIndex(rawName);
  +            else {
  +                index = m_attributes.getIndex(uri,localName);
  +            }
               if (index >= 0)
               {
                   /* We've seen the attribute before.
  @@ -376,12 +387,15 @@
                    * we really want to re-set is the value anyway.
                    */
                   m_attributes.setValue(index,value);
  +                was_added = false;
               }
               else
               {
                   // the attribute doesn't exist yet, create it
                   m_attributes.addAttribute(uri, localName, rawName, type, value);
  +                was_added = true;
               }
  +            return was_added;
           
       }
     
  @@ -402,10 +416,29 @@
               final String localName = getLocalName(patchedName);
               final String uri = getNamespaceURI(patchedName, false);
   
  -            addAttributeAlways(uri,localName, patchedName, "CDATA", value);
  +            addAttributeAlways(uri,localName, patchedName, "CDATA", value, false);
            }
       }    
   
  +    /**
  +     * Adds the given xsl:attribute to the set of collected attributes, 
  +     * but only if there is a currently open element.  This method is only
  +     * called by XSLTC.
  +     *
  +     * @param name the attribute's qualified name (prefix:localName)
  +     * @param value the value of the attribute
  +     * @param uri the URI that the prefix of the name points to
  +     */
  +    public void addXSLAttribute(String name, final String value, final String uri)
  +    {
  +        if (m_elemContext.m_startTagOpen)
  +        {
  +            final String patchedName = patchName(name);
  +            final String localName = getLocalName(patchedName);
  +
  +            addAttributeAlways(uri,localName, patchedName, "CDATA", value, true);
  +         }
  +    } 
   
       /**
        * Add the given attributes to the currently collected ones. These
  @@ -430,7 +463,8 @@
                   atts.getLocalName(i),
                   atts.getQName(i),
                   atts.getType(i),
  -                atts.getValue(i));
  +                atts.getValue(i),
  +                false);
   
           }
       }
  
  
  
  1.29      +7 -15     xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java
  
  Index: ElemAttribute.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemAttribute.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- ElemAttribute.java	17 Aug 2004 18:35:32 -0000	1.28
  +++ ElemAttribute.java	11 Feb 2005 06:18:14 -0000	1.29
  @@ -182,25 +182,17 @@
       if(null != nodeName && nodeName.length() > 0)
       {
         SerializationHandler rhandler = transformer.getSerializationHandler();
  -      if(prefix != null && prefix.length() > 0)
  -      {
  -        try
  -        {
  -          rhandler.startPrefixMapping(prefix, nodeNamespace, false);
  -        }
  -        catch(SAXException se)
  -        {
  -          throw new TransformerException(se);
  -        }
  -      }
  +
  +      // Evaluate the value of this attribute
         String val = transformer.transformToString(this);
  -      String localName = QName.getLocalPart(nodeName);
         try 
         {
  +        // Let the result tree handler add the attribute and its String value.
  +        String localName = QName.getLocalPart(nodeName);
           if(prefix != null && prefix.length() > 0){
  -            rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val);
  +            rhandler.addAttribute(nodeNamespace, localName, nodeName, "CDATA", val, true);
           }else{
  -            rhandler.addAttribute("", localName, nodeName, "CDATA", val);
  +            rhandler.addAttribute("", localName, nodeName, "CDATA", val, true);
           }
         }
         catch (SAXException e)
  
  
  
  1.46      +2 -2      xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java
  
  Index: ElemLiteralResult.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemLiteralResult.java,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -r1.45 -r1.46
  --- ElemLiteralResult.java	23 Jan 2005 00:27:29 -0000	1.45
  +++ ElemLiteralResult.java	11 Feb 2005 06:18:14 -0000	1.46
  @@ -671,7 +671,7 @@
                               avt.getName(),
                               avt.getRawName(),
                               "CDATA",
  -                            stringedValue);
  +                            stringedValue, false);
                       }
                   } // end for
               }
  
  
  
  1.6       +3 -3      xml-xalan/java/src/org/apache/xalan/serialize/SerializerUtils.java
  
  Index: SerializerUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/serialize/SerializerUtils.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- SerializerUtils.java	24 Jan 2005 00:34:35 -0000	1.5
  +++ SerializerUtils.java	11 Feb 2005 06:18:14 -0000	1.6
  @@ -73,7 +73,7 @@
                   dtm.getLocalName(attr),
                   dtm.getNodeName(attr),
                   "CDATA",
  -                dtm.getNodeValue(attr));
  +                dtm.getNodeValue(attr), false);
           }
           catch (SAXException e)
           {
  @@ -185,7 +185,7 @@
               else if (type == DTM.NAMESPACE_NODE)
               {
                   String prefix = dtm.getNodeNameX(src);
  -                // bjm - some changes here to get desturi
  +                // Brian M. - some changes here to get desturi
                   String desturi = handler.getNamespaceURIFromPrefix(prefix);
                   String srcURI = dtm.getNodeValue(src);
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org