public void startElement(String name, AttributeList atts) throws org.xml.sax.SAXException { //-- strip namespace prefix int idx = name.indexOf(':'); if (idx >= 0) { name = name.substring(idx+1); } StateInfo sInfo = null; boolean topLevel = false; //-- if we are currently in another element //-- definition...flag as complex content if (!_siStack.isEmpty()) { sInfo = (StateInfo)_siStack.peek(); sInfo.complex = true; } else { topLevel = true; } //-- create current holder for stateInformation sInfo = new StateInfo(); sInfo.topLevel = topLevel; _siStack.push(sInfo); //-- create element definition sInfo.element = new ElementDecl(_schema, name); //-- create attributes for (int i = 0; i < atts.getLength(); i++) { String attName = atts.getName(i); //-- skip namespace declarations if (attName.equals(XMLNS)) continue; String prefix = ""; idx = attName.indexOf(':'); if (idx >= 0) { prefix = attName.substring(0, idx); attName = attName.substring(idx+1); } if (prefix.equals(XMLNS)) continue; AttributeDecl attr = new AttributeDecl(_schema, attName); //-- guess simple type String typeName = _nsPrefix + ':' + DatatypeHandler.guessType(atts.getValue(i)); attr.setSimpleTypeReference(typeName); sInfo.attributes.addElement(attr); } } //-- startElement
/** * Merges the two element declarations. The resulting * merge is placed in ElementDecl e1. * * @param e1 the main ElementDecl * @param e2 the secondary ElementDecl to merge with e1 **/ private void merge(ElementDecl e1, ElementDecl e2) throws SchemaException { XMLType e1Type = e1.getType(); XMLType e2Type = e2.getType(); //-- Make sure types are not null and if so create them if (e1Type == null) { if (e2Type == null) return; //-- nothing to merge else { if (e2Type.isSimpleType()) { e1.setType(e2Type); } else { ComplexType cType = new ComplexType(_schema); Group group = new Group(); group.setOrder(_defaultGroupOrder); cType.addGroup(group); e1.setType(cType); e1Type = cType; } } } else if (e2Type == null) { if (e1Type.isSimpleType()) { e2.setType(e1Type); } else { ComplexType cType = new ComplexType(_schema); Group group = new Group(); group.setOrder(_defaultGroupOrder); cType.addGroup(group); e2.setType(cType); e2Type = cType; } } //-- both simple types if (e1Type.isSimpleType() && e2Type.isSimpleType()) { if (!e1Type.getName().equals(e2Type.getName())) { String typeName = _nsPrefix + ':' + DatatypeHandler.whichType(e1Type.getName(), e2Type.getName()); e1.setType(null); e1.setTypeReference(typeName); } return; } //-- e1 is simple, e2 is complex else if (e1Type.isSimpleType()) { ComplexType cType = new ComplexType(_schema); e1.setType(cType); Group group = new Group(); group.setOrder(_defaultGroupOrder); cType.addGroup(group); cType.setContentType(ContentType.mixed); e1Type = cType; //-- do not return here...we need to now treat as both //-- were complex } //-- e2 is simple, e1 is complex else if (e2Type.isSimpleType()) { ComplexType cType = new ComplexType(_schema); e2.setType(cType); Group group = new Group(); group.setOrder(_defaultGroupOrder); cType.addGroup(group); cType.setContentType(ContentType.mixed); e2Type = cType; //-- do not return here...we need to now treat as both //-- were complex } //-- both complex types ComplexType cType1 = (ComplexType)e1Type; ComplexType cType2 = (ComplexType)e2Type; //-- loop through all element/attribute declarations //-- of e2 and add them to e1 if they do not already exist //-- and mark them as optional Group e1Group = (Group) cType1.getParticle(0); if (e1Group == null) { e1Group = new Group(); e1Group.setOrder(_defaultGroupOrder); cType1.addGroup(e1Group); } Group e2Group = (Group) cType2.getParticle(0); if (e2Group == null) { e2Group = new Group(); e2Group.setOrder(_defaultGroupOrder); cType2.addGroup(e2Group); } Enumeration enum = e2Group.enumerate(); while (enum.hasMoreElements()) { Particle particle = (Particle)enum.nextElement(); if (particle.getStructureType() == Structure.ELEMENT) { ElementDecl element = (ElementDecl)particle; ElementDecl main = e1Group.getElementDecl(element.getName()); if (main == null) { e1Group.addElementDecl(element); element.setMinOccurs(0); } else { merge(main, element); } } } //-- add all attributes from type2 enum = cType2.getAttributeDecls(); while (enum.hasMoreElements()) { //-- check for attribute with same name AttributeDecl attNew = (AttributeDecl)enum.nextElement(); String attName = attNew.getName(); AttributeDecl attPrev = cType1.getAttributeDecl(attName); if (attPrev == null) { attNew.setUse(AttributeDecl.USE_OPTIONAL); cType1.addAttributeDecl(attNew); } else { String type1 = attPrev.getSimpleType().getName(); String type2 = attNew.getSimpleType().getName(); if (!type1.equals(type2)) { String typeName = _nsPrefix + ':' + DatatypeHandler.whichType(type1, type2); attPrev.setSimpleTypeReference(typeName); } } } //-- loop through all element/attribute declarations //-- of e1 and if they do not exist in e2, simply //-- mark them as optional enum = e1Group.enumerate(); while (enum.hasMoreElements()) { Particle particle = (Particle)enum.nextElement(); if (particle.getStructureType() == Structure.ELEMENT) { ElementDecl element = (ElementDecl)particle; if (e2Group.getElementDecl(element.getName()) == null) { element.setMinOccurs(0); } } } } //-- merge
public void endElement(String name) throws org.xml.sax.SAXException { //-- strip namespace prefix int idx = name.indexOf(':'); if (idx >= 0) { name = name.substring(idx+1); } StateInfo sInfo = (StateInfo) _siStack.pop(); //-- if we don't have a type, it means there are no //-- children and therefore the type is a simpleType or //-- simpleContent if ((sInfo.element.getType() == null) && (sInfo.buffer != null)) { //-- create SimpleType (guess type) String typeName = _nsPrefix + ':' + DatatypeHandler.guessType(sInfo.buffer.toString()); sInfo.element.setTypeReference(typeName); //-- simpleContent if (sInfo.attributes.size() > 0) { ComplexType cType = new ComplexType(_schema); //-- SHOULD CHANGE THIS TO SIMPLE CONTENT WHEN //-- SCHEMA WRITER BUGS ARE FIXED cType.setContentType(ContentType.mixed); sInfo.element.setType(cType); Group group = new Group(); group.setOrder(_defaultGroupOrder); //-- add attributes try { cType.addGroup(group); for (int i = 0; i < sInfo.attributes.size(); i++) { AttributeDecl attDecl = (AttributeDecl)sInfo.attributes.elementAt(i); cType.addAttributeDecl(attDecl); } } catch(SchemaException sx) { throw new SAXException(sx); } } } else { ComplexType cType = (ComplexType)sInfo.element.getType(); if (cType != null) { //-- add attributes try { for (int i = 0; i < sInfo.attributes.size(); i++) { AttributeDecl attDecl = (AttributeDecl)sInfo.attributes.elementAt(i); cType.addAttributeDecl(attDecl); } } catch(SchemaException sx) { throw new SAXException(sx); } } } //-- put element into parent element or as top-level in schema if (!_siStack.isEmpty()) { StateInfo parentInfo = (StateInfo)_siStack.peek(); ComplexType type = (ComplexType) parentInfo.element.getType(); Group group = null; if (type == null) { parentInfo.complex = true; type = new ComplexType(_schema); parentInfo.element.setType(type); group = new Group(); group.setOrder(_defaultGroupOrder); try { type.addGroup(group); //-- add element group.addElementDecl(sInfo.element); } catch(SchemaException sx) { throw new SAXException(sx); } } else { group = (Group) type.getParticle(0); //-- check for another element declaration with //-- same name ... ElementDecl element = group.getElementDecl(name); boolean checkGroupType = false; if (element != null) { //-- if complex...merge definition if (sInfo.complex) { try { merge(element, sInfo.element); } catch(SchemaException sx) { throw new SAXException(sx); } } element.setMaxOccurs(Particle.UNBOUNDED); checkGroupType = true; } else { try { group.addElementDecl(sInfo.element); } catch(SchemaException sx) { throw new SAXException(sx); } } //-- change group type if necessary if (checkGroupType && (group.getOrder() == Order.seq)) { //-- make sure element is last item in group, //-- otherwise we need to switch to all boolean found = false; boolean changeType = false; for (int i = 0; i < group.getParticleCount(); i++) { if (found) { changeType = true; break; } if (element == group.getParticle(i)) found = true; } if (changeType) { group.setOrder(Order.all); } } } } else { try { _schema.addElementDecl(sInfo.element); //-- make complexType top-level also //XMLType type = sInfo.element.getType(); //if ((type != null) && (type.isComplexType())) { // if (type.getName() == null) { // type.setName(sInfo.element.getName() + "Type"); // _schema.addComplexType((ComplexType)type); // } //} } catch(SchemaException sx) { throw new SAXException(sx); } } } //-- endElement