import org.w3._2001.xmlschema.Import;
import org.w3._2001.xmlschema.LocalComplexType;
import org.w3._2001.xmlschema.LocalElement;
+import org.w3._2001.xmlschema.LocalSimpleType;
import org.w3._2001.xmlschema.OpenAttrs;
+import org.w3._2001.xmlschema.Restriction;
import org.w3._2001.xmlschema.Schema;
+import org.w3._2001.xmlschema.SimpleType;
import org.w3._2001.xmlschema.TopLevelElement;
/**
String pluginName;
+ private boolean useElementNSforAttributes = true; // If true, attributes with undefined namespace are written to the same name space as teh element. If false. the attributes are written to the root namespace.
+ private boolean ignoreAttributeNS = true; // Completely ignore attribute namespaces. When true, all attributes are written to the elements.
+
private String[] header;
public XmlDataConverter(List<File> inputFiles, File conversionFile, File outputPlugin) {
Map<Schema,Map<String,Element>> elementMap = new HashMap<>();
Map<Element,String> elementNsMap = new HashMap<>();
Map<Schema,Map<String,org.w3._2001.xmlschema.Attribute>> attributeMap = new HashMap<>();
+ String defaultNS;
protected void doConvert() throws IOException, XMLStreamException, JAXBException {
XMLInputFactory input = XMLInputFactory.newInstance();
XMLEvent event = reader.nextEvent();
if (event.isStartElement()) {
StartElement parseElement = event.asStartElement();
-// System.out.println("Start " + parseElement.getName());
+
Element schemaElement = null;
String currentNS = parseElement.getName().getNamespaceURI();
Schema s = schemaMap.get(currentNS);
} else {
schemaElement = elementMap.get(s).get(elementName);
}
+
Element parentElement = elementStack.peek();
boolean newElement = false;
addSchemaDependency(ps, s);
}
+ } else {
+ defaultNS = currentNS;
}
if (schemaElement == null) {
if (elementStack.isEmpty()) {
newElement = true;
}
if (parentElement != null) {
- ComplexType complexType = parentElement.getComplexType();
+ ComplexType complexType = getOrCreateComplexType(parentElement);
ExplicitGroup choice = complexType.getChoice();
if (choice == null) {
choice = new ExplicitGroup();
// System.out.println("Attribute " + attribute.getName() + " " + attribute.getValue());
// }
if (newElement) {
- LocalComplexType complexType = new LocalComplexType();
- schemaElement.setComplexType(complexType);
attributeIterator = parseElement.getAttributes();
- while (attributeIterator.hasNext()) {
- Attribute attribute = attributeIterator.next();
- if ("http://www.w3.org/XML/1998/namespace".equals(attribute.getName().getNamespaceURI()))
- continue;
- addAttribute(attribute, complexType, currentNS);
+ if (attributeIterator.hasNext()) {
+ ComplexType complexType = getOrCreateComplexType(schemaElement);
+ while (attributeIterator.hasNext()) {
+ Attribute attribute = attributeIterator.next();
+ if ("http://www.w3.org/XML/1998/namespace".equals(attribute.getName().getNamespaceURI()))
+ continue;
+ addAttribute(attribute, complexType, currentNS);
+ }
}
} else {
- LocalComplexType complexType = schemaElement.getComplexType();
+ ComplexType complexType = schemaElement.getComplexType();
attributeIterator = parseElement.getAttributes();
- Map<String,org.w3._2001.xmlschema.Attribute> currentAttributes = new HashMap<>();
- Iterator<Annotated> currentAttributeIterator = complexType.getAttributeOrAttributeGroup().iterator();
- while (currentAttributeIterator.hasNext()) {
- Annotated annotated = currentAttributeIterator.next();
- if (annotated instanceof org.w3._2001.xmlschema.Attribute) {
- org.w3._2001.xmlschema.Attribute schemaAttribute = (org.w3._2001.xmlschema.Attribute)annotated;
- String n = schemaAttribute.getName();
- if (n != null)
- currentAttributes.put(n, schemaAttribute);
+ if (complexType != null || attributeIterator.hasNext()) {
+ complexType = getOrCreateComplexType(schemaElement);
+ Map<String,org.w3._2001.xmlschema.Attribute> currentAttributes = new HashMap<>();
+ Iterator<Annotated> currentAttributeIterator = complexType.getAttributeOrAttributeGroup().iterator();
+ while (currentAttributeIterator.hasNext()) {
+ Annotated annotated = currentAttributeIterator.next();
+ if (annotated instanceof org.w3._2001.xmlschema.Attribute) {
+ org.w3._2001.xmlschema.Attribute localAttribute = (org.w3._2001.xmlschema.Attribute)annotated;
+ String n = localAttribute.getName();
+ if (n != null)
+ currentAttributes.put(n, localAttribute);
+ else if (localAttribute.getRef() != null) {
+ currentAttributes.put(localAttribute.getRef().getLocalPart(), localAttribute);
+ }
+ }
}
- }
- while (attributeIterator.hasNext()) {
- Attribute attribute = attributeIterator.next();
- if ("http://www.w3.org/XML/1998/namespace".equals(attribute.getName().getNamespaceURI()))
- continue;
- org.w3._2001.xmlschema.Attribute schemaAttribute = currentAttributes.get(attribute.getName().getLocalPart());
- if (schemaAttribute == null) {
- addAttribute(attribute, complexType, currentNS);
- } else {
- QName newType = getType(attribute.getValue());
- updateAttributeType(schemaAttribute, newType);
+ while (attributeIterator.hasNext()) {
+ Attribute attribute = attributeIterator.next();
+ if ("http://www.w3.org/XML/1998/namespace".equals(attribute.getName().getNamespaceURI()))
+ continue;
+ org.w3._2001.xmlschema.Attribute localAttribute = currentAttributes.get(attribute.getName().getLocalPart());
+ if (localAttribute == null) {
+ addAttribute(attribute, complexType, currentNS);
+ } else {
+ QName newType = getType(attribute.getValue());
+ org.w3._2001.xmlschema.Attribute schemaAttribute = updateAttributeType(localAttribute, newType);
+
+ String attrNs = getNS(attribute, currentNS);
+ if (!ignoreAttributeNS && attribute.getName().getNamespaceURI().length() > 0) {
+ // Attribute has explicit ns definition.
+ if (localAttribute.getRef() != null) {
+ // current local attribute is reference, check that the namespaces match
+ if (!localAttribute.getRef().getNamespaceURI().equals(attrNs))
+ throw new RuntimeException("Conflicting namespaces for attribute " + attribute.getName().getLocalPart() + " " + attrNs + " " + localAttribute.getRef().getNamespaceURI());
+ } else if (!attrNs.equals(currentNS)){
+ // move the attribute to explicit namespace.
+ complexType.getAttributeOrAttributeGroup().remove(localAttribute);
+ org.w3._2001.xmlschema.Attribute scAttribute = addAttribute(attribute, complexType, currentNS);
+ scAttribute.setType(schemaAttribute.getType());
+ }
+
+ }
+ }
+
}
-
}
}
} else if (event.isCharacters()) {
Characters characters = event.asCharacters();
-// if (!characters.isWhiteSpace())
-// System.out.println(characters.getData());
+ Element element = elementStack.peek();
+ if (element != null) {
+ String text = characters.getData().trim();
+ if (text.length() > 0) {
+ setElementCharactersData(element, text, characters);
+ }
+ }
} else if (event.isNamespace()) {
}
}
}
- private void updateAttributeType(org.w3._2001.xmlschema.Attribute schemaAttribute, QName newType) {
+ private void setElementCharactersData(Element element, String text, Characters characters) {
- QName currentType = schemaAttribute.getType();
- if (!newType.getLocalPart().equals(currentType.getLocalPart())) {
-
-
- if (currentType.getLocalPart().equals("integer") && newType.getLocalPart().equals("double")) {
- // change integer to double
- schemaAttribute.setType(newType);
- } else if (currentType.getLocalPart().equals("double") && newType.getLocalPart().equals("integer")) {
- // nothing to do, integer can be parsed as double
- } else if (!currentType.getLocalPart().equals("string")){
- schemaAttribute.setType(new QName(SchemaConversionBase.SCHEMA_NS, "string"));
+ //System.out.println(element.getName() + " " + characters.getData());
+ if (element.getComplexType() != null)
+ element.getComplexType().setMixed(true);
+ else {
+ SimpleType simpleType = getOrCreateSimpleType(element);
+ QName type = getType(text);
+ Restriction restriction = simpleType.getRestriction();
+ if (restriction == null) {
+ restriction = new Restriction();
+ restriction.setBase(type);
+ simpleType.setRestriction(restriction);
+ } else {
+ restriction.setBase(mergePrimitiveType(restriction.getBase(), type));
+ }
+ }
+ }
+
+ private ComplexType getOrCreateComplexType(Element element) {
+ LocalComplexType complexType = element.getComplexType();
+ if (complexType == null) {
+ complexType = new LocalComplexType();
+ element.setComplexType(complexType);
+ if (element.getSimpleType() != null) {
+ // Convert SimpleType to ComplexType
+ element.setSimpleType(null);
+ complexType.setMixed(true);
}
}
+ return complexType;
+ }
+
+ private SimpleType getOrCreateSimpleType(Element element) {
+ LocalSimpleType simpleType = element.getSimpleType();
+ if (simpleType == null) {
+ simpleType = new LocalSimpleType();
+ element.setSimpleType(simpleType);
+ }
+ return simpleType;
}
private void addElement(ExplicitGroup choice, QName type, LocalElement localElement) {
parentSchema.getIncludeOrImportOrRedefine().add(import1);
}
- private void addAttribute(Attribute attribute, ComplexType complexType, String currentNS) {
- if (attribute.getName().getNamespaceURI().length() == 0 || attribute.getName().getNamespaceURI().equals(currentNS)) {
+ private String getNS(Attribute attribute, String currentNS) {
+ if (ignoreAttributeNS)
+ return currentNS;
+ String attrNs = attribute.getName().getNamespaceURI();
+ if (attrNs.length() == 0) {
+ if (useElementNSforAttributes)
+ attrNs = currentNS;
+ else
+ attrNs = defaultNS;
+ }
+ return attrNs;
+ }
+
+
+ private org.w3._2001.xmlschema.Attribute addAttribute(Attribute attribute, ComplexType complexType, String currentNS) {
+ String attrNs = getNS(attribute, currentNS);
+ String attrName = attribute.getName().getLocalPart();
+
+ if (attrNs.equals(currentNS)) {
org.w3._2001.xmlschema.Attribute schemaAttribute = new org.w3._2001.xmlschema.Attribute();
- schemaAttribute.setName(attribute.getName().getLocalPart());
+ schemaAttribute.setName(attrName);
schemaAttribute.setType(getType(attribute.getValue()));
addAttribute(complexType, schemaAttribute);
+ return schemaAttribute;
} else {
- {
- Schema schema = getOrCreateSchema(currentNS);
- Schema attrSchema = getOrCreateSchema(attribute.getName().getNamespaceURI());
-
- org.w3._2001.xmlschema.Attribute schemaAttribute = attributeMap.get(attrSchema).get(attribute.getName().getLocalPart());
- if (schemaAttribute == null) {
- schemaAttribute = new org.w3._2001.xmlschema.TopLevelAttribute();
- schemaAttribute.setName(attribute.getName().getLocalPart());
- schemaAttribute.setType(getType(attribute.getValue()));
- attrSchema.getSimpleTypeOrComplexTypeOrGroup().add(schemaAttribute);
- attributeMap.get(attrSchema).put(attribute.getName().getLocalPart(), schemaAttribute);
- }
- addSchemaDependency(schema, attrSchema);
-
- }
- {
- org.w3._2001.xmlschema.Attribute schemaAttribute = new org.w3._2001.xmlschema.Attribute();
- schemaAttribute.setRef(new QName(attribute.getName().getNamespaceURI(),attribute.getName().getLocalPart()));
- addAttribute(complexType, schemaAttribute);
+
+ Schema schema = getOrCreateSchema(currentNS);
+ Schema attrSchema = getOrCreateSchema(attrNs);
+
+ org.w3._2001.xmlschema.Attribute schemaAttribute = attributeMap.get(attrSchema).get(attrName);
+ if (schemaAttribute == null) {
+ schemaAttribute = new org.w3._2001.xmlschema.TopLevelAttribute();
+ schemaAttribute.setName(attrName);
+ schemaAttribute.setType(getType(attribute.getValue()));
+ attrSchema.getSimpleTypeOrComplexTypeOrGroup().add(schemaAttribute);
+ attributeMap.get(attrSchema).put(attribute.getName().getLocalPart(), schemaAttribute);
}
+ addSchemaDependency(schema, attrSchema);
+
+
+ org.w3._2001.xmlschema.Attribute localAttribute = new org.w3._2001.xmlschema.Attribute();
+ localAttribute.setRef(new QName(attrNs,attrName));
+ addAttribute(complexType, localAttribute);
+ return schemaAttribute;
+
}
}
org.w3._2001.xmlschema.Attribute attr = (org.w3._2001.xmlschema.Attribute)annotated;
if (schemaAttribute.getName().equals(attr.getName())) {
updateAttributeType(attr, schemaAttribute.getType());
+ return;
}
}
}
private QName getType(String value) {
+ if ("true".equals(value) || "false".equals(value)) // || "1".equals(value) || "0".equals(value))
+ return new QName(SchemaConversionBase.SCHEMA_NS, "boolean");
try {
Integer.parseInt(value);
return new QName(SchemaConversionBase.SCHEMA_NS, "integer");
} catch (NumberFormatException e) {
}
- if ("True".equals(value) || "False".equals(value))
- return new QName(SchemaConversionBase.SCHEMA_NS, "boolean");
+
return new QName(SchemaConversionBase.SCHEMA_NS, "string");
}
+ private org.w3._2001.xmlschema.Attribute updateAttributeType(org.w3._2001.xmlschema.Attribute schemaAttribute, QName newType) {
+
+ QName currentType = schemaAttribute.getType();
+ if (currentType == null && schemaAttribute.getRef() != null) {
+ Schema schema = schemaMap.get(schemaAttribute.getRef().getNamespaceURI());
+
+ schemaAttribute = attributeMap.get(schema).get(schemaAttribute.getRef().getLocalPart());
+ currentType = schemaAttribute.getType();
+ }
+ if (currentType == null)
+ throw new RuntimeException("Could not resolve attribute");
+
+
+ schemaAttribute.setType(mergePrimitiveType(currentType, newType));
+ return schemaAttribute;
+
+ }
+
+ private QName mergePrimitiveType(QName currentType, QName newType) {
+ if (!newType.getLocalPart().equals(currentType.getLocalPart())) {
+
+
+ if (currentType.getLocalPart().equals("integer") && newType.getLocalPart().equals("double")) {
+ // change integer to double
+ return newType;
+ } else if (currentType.getLocalPart().equals("double") && newType.getLocalPart().equals("integer")) {
+ // nothing to do, integer can be parsed as double
+ return currentType;
+ } else if (currentType.getLocalPart().equals("boolean") && newType.getLocalPart().equals("integer")) {
+ // change boolean to int
+ return newType;
+ } else if (currentType.getLocalPart().equals("integer") && newType.getLocalPart().equals("boolean")) {
+ // nothing to do, boolean (0 & 1) can be parsed as integer.
+ // FIXME : what about true / false? Now type detection system does not accept 0 or 1 as boolean values, while XML supports it. See method: QName getType(String value)
+ // FIXME : also, if we support 0 & 1 as booleans, we need to consider possible double values as well.
+ return currentType;
+ } else if (!currentType.getLocalPart().equals("string")){
+ return new QName(SchemaConversionBase.SCHEMA_NS, "string");
+ }
+ }
+ return currentType;
+ }
+
private Schema getOrCreateSchema(StartElement parseElement) {
return getOrCreateSchema(parseElement.getName().getNamespaceURI());
}