package sushi.xml.importer; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import sushi.event.SushiEventType; import sushi.event.attribute.SushiAttribute; import sushi.event.attribute.SushiAttributeTree; import sushi.event.attribute.SushiAttributeTypeEnum; /** * This class parses XSD files, which describes the schema of XML files. */ public class XSDParser extends AbstractXMLParser { private static SushiAttributeTree eventTree; /** * Creates a new {@link SushiEventType} with the given name from a XSD from the given file path. * @param filePath * @param eventTypeName * @return * @throws XMLParsingException */ public static SushiEventType generateEventTypeFromXSD(String filePath, String eventTypeName) throws XMLParsingException { Document doc = readXMLDocument(filePath); if (doc == null) { throw new XMLParsingException("could not read XSD: " + filePath); } return generateEventType(doc, eventTypeName); } /** * Creates a new {@link SushiEventType} with the given name from a XSD from the given document. * @param doc * @param schemaName * @return */ public static SushiEventType generateEventType(Document doc, String schemaName) { XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(new XSDNameSpaceContext()); // XPath Query for showing all nodes value XPathExpression rootElementExpression = null; try { rootElementExpression = xpath.compile("//xs:schema/child::xs:element"); } catch (XPathExpressionException e) { e.printStackTrace(); } Object rootElementsResult = null; try { rootElementsResult = rootElementExpression.evaluate(doc, XPathConstants.NODESET); } catch (XPathExpressionException e) { e.printStackTrace(); } NodeList rootElementNodes = (NodeList) rootElementsResult; //Jedes Root-Element wird ein EventType //Im Root-Element nach weiteren Unterelementen suchen if(!(rootElementNodes.getLength() == 1)) { System.err.println("Number of root elements is wrong, should be 1 but was " + rootElementNodes.getLength()); } Node actualRootElement = rootElementNodes.item(0); eventTree = new SushiAttributeTree(); // String eventTypeName = actualRootElement.getAttributes().getNamedItem("name").getNodeValue(); addChildElementsFromElement(actualRootElement, null, null); return new SushiEventType(schemaName, eventTree, null, schemaName); } /** * Creates a {@link SushiAttributeTree} for the given nodes. * @param actualRootElement * @param realRootElement * @param realRootAttribute * @return */ private static SushiAttributeTree addChildElementsFromElement(Node actualRootElement, Node realRootElement, SushiAttribute realRootAttribute) { NodeList childNodeList = actualRootElement.getChildNodes(); for (int i = 0; i < childNodeList.getLength(); i++) { Node childNode = childNodeList.item(i); if (childNode.getNodeType() == 1) { if (childNode.getNodeName().equals("xs:complexType") || childNode.getNodeName().equals("xs:sequence")) { addChildElementsFromElement(childNode, realRootElement, realRootAttribute); } else if(childNode.getNodeName().equals("xs:element")) { SushiAttributeTypeEnum attributeType = null; String xsElementType = null; if (childNode.getAttributes().getNamedItem("type") != null) { xsElementType = childNode.getAttributes().getNamedItem("type").getNodeValue(); } if (xsElementType == null) { // chooses String if no 'type' attribute in xs:element found attributeType = SushiAttributeTypeEnum.STRING; } else { if (xsElementType.equals("xs:decimal") || xsElementType.equals("xs:integer") || xsElementType.equals("xs:int") || xsElementType.equals("xs:float")) { attributeType = SushiAttributeTypeEnum.INTEGER; } else if (xsElementType.equals("xs:date") || xsElementType.equals("xs:time")) { attributeType = SushiAttributeTypeEnum.DATE; } else { attributeType = SushiAttributeTypeEnum.STRING; } } SushiAttribute newAttribute; String attributeName = childNode.getAttributes().getNamedItem("name").getNodeValue().trim().replaceAll(" +","_").replaceAll("[^a-zA-Z0-9_]+",""); if (realRootElement == null) { newAttribute = new SushiAttribute(attributeName, attributeType); eventTree.addRoot(newAttribute); } else { newAttribute = new SushiAttribute(realRootAttribute, attributeName, attributeType); } addChildElementsFromElement(childNode, childNode, newAttribute); } } } return eventTree; } }