protected void serializeAttList()

in serializer/src/main/java/org/apache/xml/serializer/dom3/DOM3TreeWalker.java [663:880]


    protected void serializeAttList(Element node) throws SAXException {
        NamedNodeMap atts = node.getAttributes();
        int nAttrs = atts.getLength();

        for (int i = 0; i < nAttrs; i++) {
            Node attr = atts.item(i);

            String localName = attr.getLocalName();
            String attrName = attr.getNodeName();
            String attrPrefix = attr.getPrefix() == null ? "" : attr.getPrefix();
            String attrValue = attr.getNodeValue();

            // Determine the Attr's type.
            String type = null;
            if (fIsLevel3DOM) {
                type = ((Attr) attr).getSchemaTypeInfo().getTypeName();
            }
            type = type == null ? "CDATA" : type;

            String attrNS = attr.getNamespaceURI();
            if (attrNS !=null && attrNS.length() == 0) {
            	attrNS=null;
                // we must remove prefix for this attribute
            	attrName=attr.getLocalName();
            }

            boolean isSpecified = ((Attr) attr).getSpecified();
            boolean addAttr = true;
            boolean applyFilter = false;
            boolean xmlnsAttr =
                attrName.equals("xmlns") || attrName.startsWith("xmlns:");

            // well-formed=true
            if ((fFeatures & WELLFORMED) != 0) {
                isAttributeWellFormed(attr);
            }
            
            //-----------------------------------------------------------------
            // start Attribute namespace fixup
            //-----------------------------------------------------------------
            // namespaces=true, normalize all non-namespace attributes
            // Step 3. Attribute
            if ((fFeatures & NAMESPACES) != 0 && !xmlnsAttr) {
           	
        		// If the Attr has a namespace URI
        		if (attrNS != null) {
        			attrPrefix = attrPrefix == null ? "" : attrPrefix;

        			String declAttrPrefix = fNSBinder.getPrefix(attrNS);
        			String declAttrNS = fNSBinder.getURI(attrPrefix);
        			
        			// attribute has no prefix (default namespace decl does not apply to
        			// attributes)
        			// OR
        			// attribute prefix is not declared
        			// OR
        			// conflict: attribute has a prefix that conflicts with a binding
        			if ("".equals(attrPrefix) || "".equals(declAttrPrefix)
        					|| !attrPrefix.equals(declAttrPrefix)) {

        				// namespaceURI matches an in scope declaration of one or
        				// more prefixes
        				if (declAttrPrefix != null && !"".equals(declAttrPrefix)) {
        					// pick the prefix that was found and change attribute's
        					// prefix and nodeName.
        					attrPrefix = declAttrPrefix;
        					
        					if (declAttrPrefix.length() > 0 ) { 
        						attrName = declAttrPrefix + ":" + localName;
        					} else {
        						attrName = localName;
        					}	
        				} else {
        					// The current prefix is not null and it has no in scope
        					// declaration
        					if (attrPrefix != null && !"".equals(attrPrefix)
        							&& declAttrNS == null) {
        						// declare this prefix
        						if ((fFeatures & NAMESPACEDECLS) != 0) {
        							fSerializer.addAttribute(XMLNS_URI, attrPrefix,
        									XMLNS_PREFIX + ":" + attrPrefix, "CDATA",
        									attrNS);
        							fNSBinder.declarePrefix(attrPrefix, attrNS);
        							fLocalNSBinder.declarePrefix(attrPrefix, attrNS);
        						}
        					} else {
        						// find a prefix following the pattern "NS" +index
        						// (starting at 1)
        						// make sure this prefix is not declared in the current
        						// scope.
        						int counter = 1;
        						attrPrefix = "NS" + counter++;

        						while (fLocalNSBinder.getURI(attrPrefix) != null) {
        							attrPrefix = "NS" + counter++;
        						}
        						// change attribute's prefix and Name
        						attrName = attrPrefix + ":" + localName;
        						
        						// create a local namespace declaration attribute
        						// Add the xmlns declaration attribute
        						if ((fFeatures & NAMESPACEDECLS) != 0) {
                                       							
        							fSerializer.addAttribute(XMLNS_URI, attrPrefix,
        									XMLNS_PREFIX + ":" + attrPrefix, "CDATA",
        									attrNS);
            						fNSBinder.declarePrefix(attrPrefix, attrNS);
            						fLocalNSBinder.declarePrefix(attrPrefix, attrNS);
        						}
        					}
        				}
        			}

        		} else { // if the Attr has no namespace URI
        			// Attr has no localName
        			if (localName == null) {
        				// DOM Level 1 node!
        				String msg = Utils.messages.createMessage(
        						MsgKey.ER_NULL_LOCAL_ELEMENT_NAME,
        						new Object[] { attrName });

        				if (fErrorHandler != null) {
        					fErrorHandler
        							.handleError(new DOMErrorImpl(
        									DOMError.SEVERITY_ERROR, msg,
        									MsgKey.ER_NULL_LOCAL_ELEMENT_NAME, null,
        									null, null));
        				}

        			} else { // uri=null and no colon
        				// attr has no namespace URI and no prefix
        				// no action is required, since attrs don't use default
        			}
        		}

            }

            
            // discard-default-content=true
            // Default attr's are not passed to the filter and this contraint
            // is applied only when discard-default-content=true 
            // What about default xmlns attributes???? check for xmlnsAttr
            if ((((fFeatures & DISCARDDEFAULT) != 0) && isSpecified)
                || ((fFeatures & DISCARDDEFAULT) == 0)) {
                applyFilter = true;
            } else {
            	addAttr = false;
            }

            if (applyFilter) {
                // apply the filter for Attributes that are not default attributes
                // or namespace decl attributes
                if (fFilter != null
                    && (fFilter.getWhatToShow() & NodeFilter.SHOW_ATTRIBUTE)
                        != 0) {

                    if (!xmlnsAttr) {
                        short code = fFilter.acceptNode(attr);
                        switch (code) {
                            case NodeFilter.FILTER_REJECT :
                            case NodeFilter.FILTER_SKIP :
                                addAttr = false;
                                break;
                            default : //fall through..
                        }
                    }
                }
            }

            // if the node is a namespace node
            if (addAttr && xmlnsAttr) {
                // If namespace-declarations=true, add the node , else don't add it
                if ((fFeatures & NAMESPACEDECLS) != 0) {
               		// The namespace may have been fixed up, in that case don't add it.
                	if (localName != null && !"".equals(localName)) {
                		fSerializer.addAttribute(attrNS, localName, attrName, type, attrValue);
                	} 
                }
            } else if (
                addAttr && !xmlnsAttr) { // if the node is not a namespace node
                // If namespace-declarations=true, add the node with the Attr nodes namespaceURI
                // else add the node setting it's namespace to null or else the serializer will later
                // attempt to add a xmlns attr for the prefixed attribute
                if (((fFeatures & NAMESPACEDECLS) != 0) && (attrNS != null)) {
                    fSerializer.addAttribute(
                        attrNS,
                        localName,
                        attrName,
                        type,
                        attrValue);
                } else {
                    fSerializer.addAttribute(
                        "",
                        localName,
                        attrName,
                        type,
                        attrValue);
                }
            }

            // 
            if (xmlnsAttr && ((fFeatures & NAMESPACEDECLS) != 0)) {
                int index;
                // Use "" instead of null, as Xerces likes "" for the 
                // name of the default namespace.  Fix attributed 
                // to "Steven Murray" <smurray@ebt.com>.
                String prefix =
                    (index = attrName.indexOf(":")) < 0
                        ? ""
                        : attrName.substring(index + 1);

                if (!"".equals(prefix)) {
                    fSerializer.namespaceAfterStartElement(prefix, attrValue);
                }
            }
        }
        
    }