private Attributes getAttributesWithClass(Attributes originalAttributes) { String newClassAttribute = originalAttributes.getValue("class"); if (addedClasses != null && addedClasses.length() > 0) { if (newClassAttribute == null || newClassAttribute.length() == 0) { newClassAttribute = addedClasses; } else { newClassAttribute += " " + addedClasses; } } if (newClassAttribute != null) return XMLUtils.addOrReplaceAttribute(originalAttributes, "", "", "class", newClassAttribute); else return originalAttributes; }
public void startElement(String uri, String localname, String qName, Attributes attributes) throws SAXException { namespaceSupport.startElement(); // Handle location data if (locationData == null && locator != null && mustOutputFirstElement) { final String systemId = locator.getSystemId(); if (systemId != null) { locationData = new LocationData(systemId, locator.getLineNumber(), locator.getColumnNumber()); } } // Check for XForms or extension namespaces final boolean isXForms = XFormsConstants.XFORMS_NAMESPACE_URI.equals(uri); final boolean isXXForms = XFormsConstants.XXFORMS_NAMESPACE_URI.equals(uri); final boolean isEXForms = XFormsConstants.EXFORMS_NAMESPACE_URI.equals(uri); final boolean isXBL = XFormsConstants.XBL_NAMESPACE_URI.equals(uri); final boolean isXHTML = XMLConstants.XHTML_NAMESPACE_URI.equals(uri); // TODO: how else can we handle components? // NOTE: Here we have an issue identifying which elements must have content preserved. For // example, an element // to which an XBL binding is applied should be preserved, because XBL template processing take // place during // static state analysis. In XFormsDocumentAnnotatorContentHandler, we detect XBL bindings. // Should we do the // same here again? It is wasteful to do it twice. Possibly, XFDACH could pass this information // here since // it already does all the work to detect content preservation. E.g. custom attribute. // final boolean isXFormsOrExtension = isXForms || isXXForms || isEXForms || isXBL; final boolean isXFormsOrExtension = !isXHTML && !"".equals(uri); // see NOTE above final boolean isExtension = isXFormsOrExtension && !isXForms && !isXXForms && !isEXForms && !isXBL; // see NOTE above // Handle xml:base if (!inXFormsOrExtension) { final String xmlBaseAttribute = attributes.getValue(XMLConstants.XML_URI, "base"); if (xmlBaseAttribute == null) { xmlBaseStack.push(xmlBaseStack.peek()); } else { try { final URI currentXMLBaseURI = xmlBaseStack.peek(); xmlBaseStack.push( currentXMLBaseURI .resolve(new URI(xmlBaseAttribute)) .normalize()); // normalize to remove "..", etc. } catch (URISyntaxException e) { throw new ValidationException( "Error creating URI from: '" + xmlBaseStack.peek() + "' and '" + xmlBaseAttribute + "'.", e, new LocationData(locator)); } } } // Handle properties of the form @xxforms:* when outside of models or controls if (!inXFormsOrExtension && !isXFormsOrExtension) { final int attributesCount = attributes.getLength(); for (int i = 0; i < attributesCount; i++) { final String attributeURI = attributes.getURI(i); if (XFormsConstants.XXFORMS_NAMESPACE_URI.equals(attributeURI)) { // Found xxforms:* attribute final String attributeLocalName = attributes.getLocalName(i); // Only take the first occurrence into account, and make sure the property is supported if (properties.get(attributeLocalName) == null && XFormsProperties.getPropertyDefinition(attributeLocalName) != null) { properties.put(attributeLocalName, attributes.getValue(i)); } } } } if (level > 0 || !ignoreRootElement) { // Start extracting model or controls if (!inXFormsOrExtension && isXFormsOrExtension) { inXFormsOrExtension = true; xformsLevel = level; outputFirstElementIfNeeded(); // Add xml:base on element attributes = XMLUtils.addOrReplaceAttribute( attributes, XMLConstants.XML_URI, "xml", "base", getCurrentBaseURI()); sendStartPrefixMappings(); } // Check for preserved content if (inXFormsOrExtension && !inPreserve) { // TODO: Just warn? if (isXXForms) { // Check that we are getting a valid xxforms:* element if (XFormsConstants.ALLOWED_XXFORMS_ELEMENTS.get(localname) == null && !XFormsActions.isActionName(XFormsConstants.XXFORMS_NAMESPACE_URI, localname)) throw new ValidationException( "Invalid extension element in XForms document: " + qName, new LocationData(locator)); } else if (isEXForms) { // Check that we are getting a valid exforms:* element if (XFormsConstants.ALLOWED_EXFORMS_ELEMENTS.get(localname) == null) throw new ValidationException( "Invalid eXForms element in XForms document: " + qName, new LocationData(locator)); } else if (isXBL) { // Check that we are getting a valid xbl:* element if (XFormsConstants.ALLOWED_XBL_ELEMENTS.get(localname) == null) throw new ValidationException( "Invalid XBL element in XForms document: " + qName, new LocationData(locator)); } // Preserve as is the content of labels, etc., instances, and schemas if ((XFormsConstants.LABEL_HINT_HELP_ALERT_ELEMENT.get(localname) != null // labels, etc. may contain XHTML || "instance".equals(localname)) && isXForms // XForms instances || "schema".equals(localname) && XMLConstants.XSD_URI.equals(uri) // XML schemas || "xbl".equals(localname) && isXBL // preserve everything under xbl:xbl so that templates may be processed by // static state || isExtension) { inPreserve = true; preserveLevel = level; } } // We are within preserved content or we output regular XForms content if (inXFormsOrExtension && (inPreserve || isXFormsOrExtension)) { super.startElement(uri, localname, qName, attributes); } } else { // Just open the root element outputFirstElementIfNeeded(); sendStartPrefixMappings(); super.startElement(uri, localname, qName, attributes); } level++; }