/** * Copyright 2007-2010 非也 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License v3 as published by the Free Software * Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, see http://www.gnu.org/licenses/lgpl.html. * */ package org.firesoa.common.schema; import java.io.ByteArrayOutputStream; import java.nio.charset.Charset; import java.util.List; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.lang.StringUtils; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaAll; import org.apache.ws.commons.schema.XmlSchemaAny; import org.apache.ws.commons.schema.XmlSchemaAttribute; import org.apache.ws.commons.schema.XmlSchemaAttributeGroup; import org.apache.ws.commons.schema.XmlSchemaAttributeGroupMember; import org.apache.ws.commons.schema.XmlSchemaAttributeGroupRef; import org.apache.ws.commons.schema.XmlSchemaAttributeOrGroupRef; import org.apache.ws.commons.schema.XmlSchemaChoice; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaComplexContent; import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension; import org.apache.ws.commons.schema.XmlSchemaComplexContentRestriction; import org.apache.ws.commons.schema.XmlSchemaComplexType; import org.apache.ws.commons.schema.XmlSchemaContent; import org.apache.ws.commons.schema.XmlSchemaContentModel; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.XmlSchemaForm; import org.apache.ws.commons.schema.XmlSchemaGroup; import org.apache.ws.commons.schema.XmlSchemaGroupRef; import org.apache.ws.commons.schema.XmlSchemaObject; import org.apache.ws.commons.schema.XmlSchemaParticle; import org.apache.ws.commons.schema.XmlSchemaSequence; import org.apache.ws.commons.schema.XmlSchemaSequenceMember; import org.apache.ws.commons.schema.XmlSchemaSimpleContent; import org.apache.ws.commons.schema.XmlSchemaSimpleType; import org.apache.ws.commons.schema.XmlSchemaType; import org.apache.ws.commons.schema.constants.Constants; import org.apache.ws.commons.schema.utils.XmlSchemaRef; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * * * @author 非也 nychen2000@163.com Fire Workflow 官方网站:www.firesoa.com 或者 * www.fireflow.org * */ public class DOMInitializer { private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory .newInstance(); private static final TransformerFactory transformerFactory = TransformerFactory .newInstance(); public static String dom2String(Document dom) { try { Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, Charset.defaultCharset().name()); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // transformer.transform()方法 将 XML Source转换为 Result transformer.transform(new DOMSource(dom), new StreamResult( outputStream)); return outputStream.toString(); } catch (Exception e) { e.printStackTrace(); return null; } } public static Document generateDocument( XmlSchemaCollection xmlSchemaCollection, QName rootElementQName) throws ParserConfigurationException { return generateDocument(xmlSchemaCollection, rootElementQName, false); } /** * 根据schema创建一个示例Document * * @param xmlSchemaCollection * Schema * @param rootElementQName * 根元素的QName * @param createChoice * 遇到XSD中的schema指示器时,是否创建choice中的元素。默认应该不创建。 * @return * @throws ParserConfigurationException */ public static Document generateDocument( XmlSchemaCollection xmlSchemaCollection, QName rootElementQName, boolean createChoice) throws ParserConfigurationException { XmlSchemaElement xmlSchemaElement = xmlSchemaCollection .getElementByQName(rootElementQName); if (xmlSchemaElement==null) return null; DocumentBuilder docBuilder = documentBuilderFactory .newDocumentBuilder(); Document doc = docBuilder.newDocument(); createElement(doc, doc, null, xmlSchemaElement, xmlSchemaCollection, createChoice); return doc; } /** * 创建一个Element节点 * @param doc * @param parentNode * @param childSchemaElement * @param xmlSchemaCollection * @param createChoice */ protected static void createElement(Document doc, Node parentNode, XmlSchemaElement parentSchemaElement, XmlSchemaElement childSchemaElement, XmlSchemaCollection xmlSchemaCollection, boolean createChoice) { // 1、创建根节点 XmlSchemaRef<XmlSchemaElement> ref = childSchemaElement.getRef(); if (ref != null && ref.getTarget() != null) { childSchemaElement = ref.getTarget(); } if (childSchemaElement.getName().equals("foo_1")){ System.out.println("this is foo_1"); } QName parentElmTypeQName = null; if (parentSchemaElement!=null){ parentElmTypeQName = parentSchemaElement.getSchemaTypeName(); if (parentElmTypeQName==null){ parentElmTypeQName = parentSchemaElement.getSchemaType().getQName(); } } XmlSchemaForm schemaElementForm = childSchemaElement.getForm(); QName childElmQName = childSchemaElement.getQName(); Element childElem = null; if (schemaElementForm!=null && XmlSchemaForm.QUALIFIED.equals(schemaElementForm)){ childElem = doc.createElementNS(childElmQName.getNamespaceURI(), getQualifiedName(doc, childElmQName)); }else{ if (parentElmTypeQName==null || !equalStrings(parentElmTypeQName.getNamespaceURI(),childElmQName.getNamespaceURI()) ){ //根节点 childElem = doc.createElementNS(childElmQName.getNamespaceURI(), getQualifiedName(doc, childElmQName)); } else{ //其他节点都不需要namespace prefix childElem = doc.createElement(childElmQName.getLocalPart()); } } parentNode.appendChild(childElem); // 2、初始化属性及下级节点 XmlSchemaType xmlSchemaType = childSchemaElement.getSchemaType(); if (xmlSchemaType == null) { QName qname = childSchemaElement.getSchemaTypeName(); xmlSchemaType = xmlSchemaCollection.getTypeByQName(qname); } if (xmlSchemaType instanceof XmlSchemaSimpleType) { // 简单类型 XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) xmlSchemaType; String value = ""; if (!StringUtils.isEmpty(childSchemaElement.getFixedValue())) { value = childSchemaElement.getFixedValue(); } else if (!StringUtils.isEmpty(childSchemaElement.getDefaultValue())) { value = childSchemaElement.getDefaultValue(); } if (!StringUtils.isEmpty(value)) { childElem.appendChild(doc.createTextNode(value)); } } else if (xmlSchemaType instanceof XmlSchemaComplexType) { XmlSchemaComplexType complexType = (XmlSchemaComplexType) xmlSchemaType; createChildNode4ComplexType(doc, childElem,childSchemaElement, complexType, xmlSchemaCollection, createChoice); } } /** * 创建Element的子Node,包括创建属性和子Element * @param doc * @param parentElement * @param parentSchemaElementComplexType * @param xmlSchemaCollection * @param createChoice */ protected static void createChildNode4ComplexType(Document doc, Element parentElement,XmlSchemaElement parentSchemaElement, XmlSchemaComplexType parentSchemaElementComplexType, XmlSchemaCollection xmlSchemaCollection, boolean createChoice) { // 2.1 初始化attribute List<XmlSchemaAttributeOrGroupRef> attributeSchemaList = parentSchemaElementComplexType .getAttributes(); for (XmlSchemaAttributeOrGroupRef attrOrGroupRef : attributeSchemaList) { createAttribute(doc, parentElement, (XmlSchemaAttributeGroupMember) attrOrGroupRef); } // 2.2初始化子节点 // TODO 仅处理了Particle的情况,ComplextContent的情况待处理 XmlSchemaParticle particle = parentSchemaElementComplexType.getParticle(); if (particle != null) { if (particle instanceof XmlSchemaAll) { XmlSchemaAll schemaAll = (XmlSchemaAll) particle; List<XmlSchemaElement> items = schemaAll.getItems(); for (XmlSchemaElement item : items) { createElement(doc, parentElement,parentSchemaElement, item, xmlSchemaCollection, createChoice); } } else if (particle instanceof XmlSchemaSequence) { XmlSchemaSequence schemaSeq = (XmlSchemaSequence) particle; createChildElement4Sequence(doc, parentElement,parentSchemaElement, schemaSeq, xmlSchemaCollection, createChoice); } else if (particle instanceof XmlSchemaChoice) { createChildElement4Choice(doc, parentElement,parentSchemaElement, (XmlSchemaChoice) particle, xmlSchemaCollection, createChoice); } else if (particle instanceof XmlSchemaGroupRef) { // TODO 如何处理? } } else { XmlSchemaContentModel contentModel = parentSchemaElementComplexType.getContentModel(); if (contentModel instanceof XmlSchemaComplexContent) { XmlSchemaComplexContent complexContentModel = (XmlSchemaComplexContent) contentModel; XmlSchemaContent complexContent = complexContentModel .getContent(); if (complexContent instanceof XmlSchemaComplexContentExtension) { XmlSchemaComplexContentExtension complexContentExtension = (XmlSchemaComplexContentExtension) complexContent; createChildElement4ComplexContentExtension(doc, parentElement,parentSchemaElement, complexContentExtension, xmlSchemaCollection, createChoice); } else if (complexContent instanceof XmlSchemaComplexContentRestriction) { //TODO 待处理 } } else if (contentModel instanceof XmlSchemaSimpleContent) { // TODO simple } } } protected static void createChildElement4ComplexContentExtension( Document doc, Element parentElement,XmlSchemaElement parentSchemaElement, XmlSchemaComplexContentExtension complexContentExtension, XmlSchemaCollection xmlSchemaCollection, boolean createChoice) { QName baseTypeQName = complexContentExtension.getBaseTypeName(); XmlSchemaComplexType comlexBaseType = (XmlSchemaComplexType) xmlSchemaCollection .getTypeByQName(baseTypeQName); createChildNode4ComplexType(doc, parentElement,parentSchemaElement, comlexBaseType, xmlSchemaCollection, createChoice); // 2.1 初始化attribute List<XmlSchemaAttributeOrGroupRef> attributeSchemaList = complexContentExtension .getAttributes(); for (XmlSchemaAttributeOrGroupRef attrOrGroupRef : attributeSchemaList) { createAttribute(doc, parentElement, (XmlSchemaAttributeGroupMember) attrOrGroupRef); } // 2.2初始化子节点 // TODO 仅处理了Particle的情况,ComplextContent的情况待处理 XmlSchemaParticle particle = complexContentExtension.getParticle(); if (particle != null) { if (particle instanceof XmlSchemaAll) { XmlSchemaAll schemaAll = (XmlSchemaAll) particle; List<XmlSchemaElement> items = schemaAll.getItems(); for (XmlSchemaElement item : items) { createElement(doc, parentElement, parentSchemaElement,item, xmlSchemaCollection, createChoice); } } else if (particle instanceof XmlSchemaSequence) { XmlSchemaSequence schemaSeq = (XmlSchemaSequence) particle; createChildElement4Sequence(doc, parentElement, parentSchemaElement,schemaSeq, xmlSchemaCollection, createChoice); } else if (particle instanceof XmlSchemaChoice) { createChildElement4Choice(doc, parentElement,parentSchemaElement, (XmlSchemaChoice) particle, xmlSchemaCollection, createChoice); } else if (particle instanceof XmlSchemaGroupRef) { // TODO 如何处理? } } } protected static void createChildElement4Sequence(Document doc, Element parentElement, XmlSchemaElement parentSchemaElement,XmlSchemaSequence sequence, XmlSchemaCollection xmlSchemaCollection, boolean createChoice) { List<XmlSchemaSequenceMember> items = sequence.getItems(); for (XmlSchemaSequenceMember item : items) { if (item instanceof XmlSchemaElement) { createElement(doc, parentElement,parentSchemaElement, ((XmlSchemaElement) item), xmlSchemaCollection, createChoice); } else if (item instanceof XmlSchemaSequence) { createChildElement4Sequence(doc, parentElement,parentSchemaElement, ((XmlSchemaSequence) item), xmlSchemaCollection, createChoice); } else if (item instanceof XmlSchemaChoice) { createChildElement4Choice(doc, parentElement, parentSchemaElement, ((XmlSchemaChoice) item), xmlSchemaCollection, createChoice); } else if (item instanceof XmlSchemaAny) { // TODO } else if (item instanceof XmlSchemaGroup) { // TODO } else if (item instanceof XmlSchemaGroupRef) { // TODO } } } protected static void createChildElement4Choice(Document doc, Element parentElement, XmlSchemaElement parentSchemaElement, XmlSchemaChoice choice, XmlSchemaCollection xmlSchemaCollection, boolean createChoice) { if (!createChoice) return; List<XmlSchemaObject> choiceMember = choice.getItems(); for (XmlSchemaObject schemaObj : choiceMember) { if (schemaObj instanceof XmlSchemaElement) { createElement(doc, parentElement, parentSchemaElement,((XmlSchemaElement) schemaObj), xmlSchemaCollection, createChoice); } else if (schemaObj instanceof XmlSchemaSequence) { createChildElement4Sequence(doc, parentElement,parentSchemaElement, ((XmlSchemaSequence) schemaObj), xmlSchemaCollection, createChoice); } else if (schemaObj instanceof XmlSchemaChoice) { createChildElement4Choice(doc, parentElement,parentSchemaElement, ((XmlSchemaChoice) schemaObj), xmlSchemaCollection, createChoice); } } } //TODO 需要进一步区分attribute qualified和unqualified protected static void createAttribute(Document doc, Element elem, XmlSchemaAttributeGroupMember attrMember) { if (attrMember instanceof XmlSchemaAttribute) { XmlSchemaAttribute attrSchema = (XmlSchemaAttribute) attrMember; XmlSchemaForm attrForm = attrSchema.getForm(); Attr attr = null; QName attrSchemaQName = attrSchema.getQName(); if (XmlSchemaForm.QUALIFIED.equals(attrForm)){ String attrQualifiedName = getQualifiedName(doc,attrSchemaQName); attr = doc.createAttributeNS(attrSchemaQName.getNamespaceURI(),attrQualifiedName); }else{ attr = doc.createAttribute(attrSchema.getName()); } elem.setAttributeNode(attr); String value = ""; if (!StringUtils.isEmpty(attrSchema.getFixedValue())) { value = attrSchema.getFixedValue(); } else if (!StringUtils.isEmpty(attrSchema.getDefaultValue())) { value = attrSchema.getDefaultValue(); } if (!StringUtils.isEmpty(value)) { attr.setValue(value); } } else if (attrMember instanceof XmlSchemaAttributeGroupRef) { XmlSchemaAttributeGroupRef attrGroupRef = (XmlSchemaAttributeGroupRef) attrMember; List<XmlSchemaAttributeGroupMember> groupMembers = attrGroupRef .getRef().getTarget().getAttributes(); for (XmlSchemaAttributeGroupMember groupMember : groupMembers) { createAttribute(doc, elem, groupMember); } } else if (attrMember instanceof XmlSchemaAttributeGroup) { XmlSchemaAttributeGroup attrGroup = (XmlSchemaAttributeGroup) attrMember; List<XmlSchemaAttributeGroupMember> groupMembers = attrGroup .getAttributes(); for (XmlSchemaAttributeGroupMember groupMember : groupMembers) { createAttribute(doc, elem, groupMember); } } } private static boolean equalStrings(String s1, String s2) { if (s1 == s2) { return true; } s1 = s1 == null ? "" : s1.trim(); s2 = s2 == null ? "" : s2.trim(); return s1.equals(s2); } private static String getQualifiedName(Document doc, QName qName) { Element rootElement = (Element) doc.getDocumentElement(); if (rootElement != null && !equalStrings(qName.getNamespaceURI(), rootElement.getNamespaceURI())) { // Attr attrTmp = rootElement.getAttributeNodeNS(Constants.XMLNS_ATTRIBUTE_NS_URI, "ns0"); // System.out.println("===========found attrTmp=="+attrTmp); String nsPrefix = null; nsPrefix = rootElement.lookupPrefix(qName.getNamespaceURI()); if (nsPrefix==null || nsPrefix.trim().equals("")){ int nsNumber = 1; NamedNodeMap attrMap = rootElement.getAttributes(); int length = attrMap.getLength(); for (int i = 0; i < length; i++) { Attr attr = (Attr) attrMap.item(i); String name = attr.getName(); if (name.startsWith(Constants.XMLNS_ATTRIBUTE)) { if (attr.getValue().equals(qName.getNamespaceURI())) { // Namespace已经声明了 nsPrefix = attr.getLocalName(); break; } nsNumber++; } } if (nsPrefix == null) { nsPrefix = "ns" + nsNumber; } } Attr attr = doc.createAttributeNS(Constants.XMLNS_ATTRIBUTE_NS_URI, Constants.XMLNS_ATTRIBUTE + ":" + nsPrefix); attr.setValue(qName.getNamespaceURI()); rootElement.setAttributeNode(attr); return nsPrefix + ":" + qName.getLocalPart(); } else { return "ns0:"+qName.getLocalPart(); } } protected static XmlSchema findXmlSchema(XmlSchemaCollection schemaCollection ,String targetNsUri){ XmlSchema[] xmlSchemas = schemaCollection.getXmlSchemas(); String tmpUri = targetNsUri; if (tmpUri==null){ tmpUri=""; } for (XmlSchema schema : xmlSchemas){ if (tmpUri.equals(schema.getTargetNamespace())){ return schema; } } return null; } // protected static XmlSchemaForm findElementFormDefault(XmlSchemaCollection schemaCollection ,String targetNsUri){ // XmlSchema schema = findXmlSchema(schemaCollection,targetNsUri); // if (schema!=null){ // return schema.getElementFormDefault(); // } // return XmlSchemaForm.UNQUALIFIED; // } }