XSDUtils.java
- /*
- f * GovWay - A customizable API Gateway
- * https://govway.org
- *
- * Copyright (c) 2005-2025 Link.it srl (https://link.it).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3, 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 General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- package org.openspcoop2.utils.xml;
- import java.io.File;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import org.slf4j.Logger;
- import org.w3c.dom.Attr;
- import org.w3c.dom.Document;
- import org.w3c.dom.Element;
- import org.w3c.dom.Node;
- import org.w3c.dom.NodeList;
- /**
- * Classe utilizzabile per ottenere informazioni sugli schemi
- *
- *
- * @author Poli Andrea (apoli@link.it)
- * @author $Author$
- * @version $Rev$, $Date$
- */
- public class XSDUtils {
- private AbstractXMLUtils xmlUtils;
- public XSDUtils(AbstractXMLUtils xmlUtils){
- this.xmlUtils = xmlUtils;
- }
- // IS SCHEMA
- public boolean isXSDSchema(byte[]xsd) throws XMLException {
- try{
- if(!this.xmlUtils.isDocument(xsd)){
- return false;
- }
- Document docXML = this.xmlUtils.newDocument(xsd);
- Element elemXML = docXML.getDocumentElement();
- return this.isXSDSchema(elemXML);
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
- public boolean isXSDSchema(Document xsd) throws XMLException {
- Element elemXML = xsd.getDocumentElement();
- return this.isXSDSchema(elemXML);
- }
- public boolean isXSDSchema(Element xsd) throws XMLException {
- return this.isXSDSchema((Node)xsd);
- }
- public boolean isXSDSchema(Node xsd) throws XMLException {
- try{
- if(xsd == null){
- throw new Exception("Schema xsd da verificare non definito");
- }
- //System.out.println("LOCAL["+xsd.getLocalName()+"] NAMESPACE["+xsd.getNamespaceURI()+"]");
- if(!"schema".equals(xsd.getLocalName())){
- return false;
- }
- if(!"http://www.w3.org/2001/XMLSchema".equals(xsd.getNamespaceURI())){
- return false;
- }
- return true;
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
- // TARGET NAMESPACE
- public String getTargetNamespace(byte[]xsd) throws XMLException {
- try{
- if(!this.xmlUtils.isDocument(xsd)){
- throw new Exception("Schema xsd non e' un documento valido");
- }
- Document docXML = this.xmlUtils.newDocument(xsd);
- Element elemXML = docXML.getDocumentElement();
- return this.getTargetNamespace(elemXML);
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
- public String getTargetNamespace(Document xsd) throws XMLException {
- Element elemXML = xsd.getDocumentElement();
- return this.getTargetNamespace(elemXML);
- }
- public String getTargetNamespace(Element xsd) throws XMLException {
- return this.getTargetNamespace((Node)xsd);
- }
- public String getTargetNamespace(Node xsd) throws XMLException {
- try{
- if(xsd == null){
- throw new Exception("Schema xsd non e' un documento valido");
- }
- //System.out.println("LOCAL["+elemXML.getLocalName()+"] NAMESPACE["+elemXML.getNamespaceURI()+"]");
- if(!"schema".equals(xsd.getLocalName())){
- throw new Exception("Root element non e' uno schema xsd ("+xsd.getLocalName()+")");
- }
- String targetNamespace = this.xmlUtils.getAttributeValue(xsd, "targetNamespace");
- //System.out.println("TARGET["+targetNamespace+"]");
- return targetNamespace;
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
-
-
- // SCHEMA LOCATION
- public void updateSchemaLocation(Node schemaImportInclude, String newLocation){
-
- //System.out.println("------------------------- updateSchemaLocation -------------------------------");
-
- if(schemaImportInclude!=null && schemaImportInclude.getAttributes()!=null && schemaImportInclude.getAttributes().getLength()>0){
-
- // try{
- // System.out.println(" PRIMA: "+this.xmlUtils.toString(schemaImportInclude));
- // }catch(Exception e){System.out.println("ERRORE PRIMA");}
-
- Attr oldSchemaLocation = (Attr) schemaImportInclude.getAttributes().getNamedItem("schemaLocation");
- this.xmlUtils.removeAttribute(oldSchemaLocation, (Element)schemaImportInclude);
-
- // try{
- // System.out.println(" REMOVE: "+this.xmlUtils.toString(schemaImportInclude));
- // }catch(Exception e){System.out.println("ERRORE REMOVE");}
-
- oldSchemaLocation.setValue(newLocation);
- this.xmlUtils.addAttribute(oldSchemaLocation, (Element)schemaImportInclude);
-
- // try{
- // System.out.println(" DOPO: "+this.xmlUtils.toString(schemaImportInclude));
- // }catch(Exception e){System.out.println("ERRORE DOPO");}
- }
-
- }
-
-
-
-
-
- // IMPORT
- public String getImportNamespace(Node xsd) throws XMLException {
- try{
- if(xsd == null){
- throw new Exception("Non e' un import valido");
- }
- //System.out.println("LOCAL["+elemXML.getLocalName()+"] NAMESPACE["+elemXML.getNamespaceURI()+"]");
- if(!"import".equals(xsd.getLocalName())){
- throw new Exception("Root element non e' un import di uno schema xsd ("+xsd.getLocalName()+")");
- }
- String targetNamespace = this.xmlUtils.getAttributeValue(xsd, "namespace");
- //System.out.println("TARGET["+targetNamespace+"]");
- return targetNamespace;
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
- public String getImportSchemaLocation(Node xsd) throws XMLException {
- try{
- if(xsd == null){
- throw new Exception("Non e' un import valido");
- }
- //System.out.println("LOCAL["+elemXML.getLocalName()+"] NAMESPACE["+elemXML.getNamespaceURI()+"]");
- if(!"import".equals(xsd.getLocalName())){
- throw new Exception("Root element non e' un import di uno schema xsd ("+xsd.getLocalName()+")");
- }
- String targetNamespace = this.xmlUtils.getAttributeValue(xsd, "schemaLocation");
- //System.out.println("TARGET["+targetNamespace+"]");
- return targetNamespace;
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
-
- public boolean isSchemaWithOnlyImports(Node xsd) throws XMLException {
- if(this.isXSDSchema(xsd)==false){
- throw new XMLException("Il parametro fornito non è uno schema"); // non è uno schmea
- }
- List<Node> listChild = this.xmlUtils.getNotEmptyChildNodes(xsd, false);
- if(listChild==null || listChild.size()<=0){
- return false; // schema vuoto
- }
- boolean schemaConSoloImports = true;
- for (int j = 0; j < listChild.size(); j++) {
- if( !(
- "import".equals(listChild.get(j).getLocalName())
- &&
- "http://www.w3.org/2001/XMLSchema".equals(listChild.get(j).getNamespaceURI())
- )
- ){
- schemaConSoloImports = false;
- break;
- }
- }
- return schemaConSoloImports;
- }
- // INCLUDE
- public String getIncludeSchemaLocation(Node xsd) throws XMLException {
- try{
- if(xsd == null){
- throw new Exception("Non e' un import valido");
- }
- //System.out.println("LOCAL["+elemXML.getLocalName()+"] NAMESPACE["+elemXML.getNamespaceURI()+"]");
- if(!"include".equals(xsd.getLocalName())){
- throw new Exception("Root element non e' un include di uno schema xsd ("+xsd.getLocalName()+")");
- }
- String targetNamespace = this.xmlUtils.getAttributeValue(xsd, "schemaLocation");
- //System.out.println("TARGET["+targetNamespace+"]");
- return targetNamespace;
- }catch(Exception e){
- throw new XMLException(e.getMessage(),e);
- }
- }
-
- public boolean isSchemaWithOnlyIncludes(Node xsd) throws XMLException {
- if(this.isXSDSchema(xsd)==false){
- throw new XMLException("Il parametro fornito non è uno schema"); // non è uno schmea
- }
- List<Node> listChild = this.xmlUtils.getNotEmptyChildNodes(xsd, false);
- if(listChild==null || listChild.size()<=0){
- return false; // schema vuoto
- }
- boolean schemaConSoloIncludes = true;
- for (int j = 0; j < listChild.size(); j++) {
- if( !(
- "include".equals(listChild.get(j).getLocalName())
- &&
- "http://www.w3.org/2001/XMLSchema".equals(listChild.get(j).getNamespaceURI())
- )
- ){
- schemaConSoloIncludes = false;
- break;
- }
- }
- return schemaConSoloIncludes;
- }
-
-
-
- // IMPORT - INCLUDE
-
- public boolean isSchemaWithOnlyImportsAndIncludes(Node xsd) throws XMLException {
- if(this.isXSDSchema(xsd)==false){
- throw new XMLException("Il parametro fornito non è uno schema"); // non è uno schmea
- }
- List<Node> listChild = this.xmlUtils.getNotEmptyChildNodes(xsd, false);
- if(listChild==null || listChild.size()<=0){
- return false; // schema vuoto
- }
- boolean schemaConSoloImportsAndIncludes = true;
- for (int j = 0; j < listChild.size(); j++) {
- if( !(
- ( "import".equals(listChild.get(j).getLocalName()) || "include".equals(listChild.get(j).getLocalName()) )
- &&
- "http://www.w3.org/2001/XMLSchema".equals(listChild.get(j).getNamespaceURI())
- )
- ){
- schemaConSoloImportsAndIncludes = false;
- break;
- }
- }
- return schemaConSoloImportsAndIncludes;
- }
- // READ
- public List<Node> readImportsAndIncludes(Document xsd) throws XMLException{
- return this.readImportsIncludes(null,xsd,null, true, true);
- }
- public List<Node> readImports(Document xsd) throws XMLException{
- return this.readImportsIncludes(null,xsd,null, true, false);
- }
- public List<Node> readIncludes(Document xsd) throws XMLException{
- return this.readImportsIncludes(null,xsd,null, false, true);
- }
- public List<Node> readImportsAndIncludes(Element xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, true, true);
- }
- public List<Node> readImports(Element xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, true, false);
- }
- public List<Node> readIncludes(Element xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, false, true);
- }
- public List<Node> readImportsAndIncludes(String targetNamespaceSchema,Element xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, true, true);
- }
- public List<Node> readImports(String targetNamespaceSchema,Element xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, true, false);
- }
- public List<Node> readIncludes(String targetNamespaceSchema,Element xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, false, true);
- }
- public List<Node> readImportsAndIncludes(Node xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, true, true);
- }
- public List<Node> readImports(Node xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, true, false);
- }
- public List<Node> readIncludes(Node xsd) throws XMLException{
- return this.readImportsIncludes(null,null,xsd, false, true);
- }
- public List<Node> readImportsAndIncludes(String targetNamespaceSchema,Node xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, true, true);
- }
- public List<Node> readImports(String targetNamespaceSchema,Node xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, true, false);
- }
- public List<Node> readIncludes(String targetNamespaceSchema,Node xsd) throws XMLException{
- return this.readImportsIncludes(targetNamespaceSchema,null,xsd, false, true);
- }
- private List<Node> readImportsIncludes(String targetNamespaceSchema,Document xsdD,Node xsdE,boolean imports,boolean includes) throws XMLException{
- try{
- List<Node> nodes = new ArrayList<Node>();
- NodeList list = null;
- if(xsdD!=null){
- list = xsdD.getChildNodes();
- }else{
- list = xsdE.getChildNodes();
- }
- if(list!=null){
- for(int i=0; i<list.getLength(); i++){
- Node child = list.item(i);
- if("schema".equals(child.getLocalName())){
- if(targetNamespaceSchema==null){
- try{
- targetNamespaceSchema = this.getTargetNamespace(child);
- }catch(Exception e){}
- }
- NodeList listDefinition = child.getChildNodes();
- if(listDefinition!=null){
- for(int j=0; j<listDefinition.getLength(); j++){
- Node childDefinition = listDefinition.item(j);
- if(imports){
- if("import".equals(childDefinition.getLocalName())){
- if(targetNamespaceSchema==null){
- try{
- targetNamespaceSchema = this.getImportNamespace(childDefinition);
- }catch(Exception e){}
- }
- childDefinition.setUserData("TargetNamespaceSchema", targetNamespaceSchema, null);
- nodes.add(childDefinition);
- }
- }
- if(includes){
- if("include".equals(childDefinition.getLocalName())){
- childDefinition.setUserData("TargetNamespaceSchema", targetNamespaceSchema, null);
- nodes.add(childDefinition);
- }
- }
- }
- }
- }
- else if("import".equals(child.getLocalName())){
- if(imports){
- if(targetNamespaceSchema==null){
- try{
- targetNamespaceSchema = this.getImportNamespace(child);
- }catch(Exception e){}
- }
- child.setUserData("TargetNamespaceSchema", targetNamespaceSchema, null);
- nodes.add(child);
- }
- }
- else if("include".equals(child.getLocalName())){
- if(includes){
- if(targetNamespaceSchema == null){
- throw new XMLException("Lo schema esegue un include senza definire un targetNamespace.");
- }
- child.setUserData("TargetNamespaceSchema", targetNamespaceSchema, null);
- nodes.add(child);
- }
- }
- }
- }
- return nodes;
- }catch(Exception e){
- throw new XMLException("Riscontrato errore durante la lettura dello schema: "+e.getMessage(),e);
- }
- }
- // REMOVE
- public void removeImport(Document xsd,Node importNode){
- this.removeImports_engine(xsd,null,true,false,importNode);
- }
- public void removeInclude(Document xsd,Node includeNode){
- this.removeImports_engine(xsd,null,false,true,includeNode);
- }
- public void removeImport(Element xsd,Node importNode){
- this.removeImports_engine(null,xsd,true,false,importNode);
- }
- public void removeInclude(Element xsd,Node includeNode){
- this.removeImports_engine(null,xsd,false,true,includeNode);
- }
- public void removeImport(Node xsd,Node importNode){
- this.removeImports_engine(null,xsd,true,false,importNode);
- }
- public void removeInclude(Node xsd,Node includeNode){
- this.removeImports_engine(null,xsd,false,true,includeNode);
- }
- public void removeImports(Document xsd){
- this.removeImports_engine(xsd,null,true,false,null);
- }
- public void removeIncludes(Document xsd){
- this.removeImports_engine(xsd,null,false,true,null);
- }
- public void removeImportsAndIncludes(Document xsd){
- this.removeImports_engine(xsd,null,true,true,null);
- }
- public void removeImports(Element xsd){
- this.removeImports_engine(null,xsd,true,false,null);
- }
- public void removeIncludes(Element xsd){
- this.removeImports_engine(null,xsd,false,true,null);
- }
- public void removeImportsAndIncludes(Element xsd){
- this.removeImports_engine(null,xsd,true,true,null);
- }
- public void removeImports(Node xsd){
- this.removeImports_engine(null,xsd,true,false,null);
- }
- public void removeIncludes(Node xsd){
- this.removeImports_engine(null,xsd,false,true,null);
- }
- public void removeImportsAndIncludes(Node xsd){
- this.removeImports_engine(null,xsd,true,true,null);
- }
- private void removeImports_engine(Document xsdD,Node xsdE,boolean imports,boolean includes,Node importIncludeNode){
- NodeList list = null;
- if(xsdD!=null){
- list = xsdD.getChildNodes();
- }else{
- list = xsdE.getChildNodes();
- }
- if(list!=null){
- for(int i=0; i<list.getLength(); i++){
- Node child = list.item(i);
- if("schema".equals(child.getLocalName())){
- NodeList listDefinition = child.getChildNodes();
- if(listDefinition!=null){
- for(int j=0; j<listDefinition.getLength(); j++){
- Node childDefinition = listDefinition.item(j);
- if(imports){
- if("import".equals(childDefinition.getLocalName())){
- if(importIncludeNode==null){
- child.removeChild(childDefinition);
- }else{
- if(importIncludeNode.equals(childDefinition)){
- child.removeChild(childDefinition);
- }
- }
- }
- }
- if(includes){
- if("include".equals(childDefinition.getLocalName())){
- if(importIncludeNode==null){
- child.removeChild(childDefinition);
- }else{
- if(importIncludeNode.equals(childDefinition)){
- child.removeChild(childDefinition);
- }
- }
- }
- }
- }
- }
- }
- else if("import".equals(child.getLocalName())){
- if(imports){
- if(importIncludeNode==null){
- if(xsdD!=null){
- xsdD.removeChild(child);
- }else{
- xsdE.removeChild(child);
- }
- }else{
- if(importIncludeNode.equals(child)){
- if(xsdD!=null){
- xsdD.removeChild(child);
- }else{
- xsdE.removeChild(child);
- }
- }
- }
- }
- }
- else if("include".equals(child.getLocalName())){
- if(includes){
- if(importIncludeNode==null){
- if(xsdD!=null){
- xsdD.removeChild(child);
- }else{
- xsdE.removeChild(child);
- }
- }
- else{
- if(importIncludeNode.equals(child)){
- if(xsdD!=null){
- xsdD.removeChild(child);
- }else{
- xsdE.removeChild(child);
- }
- }
- }
- }
- }
- }
- }
- }
-
-
-
-
-
-
-
-
-
- // BUILD SCHEMA COLLECTION
-
- public XSDSchemaCollection buildSchemaCollection(Map<String, byte[]> resources,Map<String, List<String>> mappingNamespaceLocations,Logger logger) throws XMLException {
- // --------- Check esistenza almeno 1 schema ---------
- if(resources.size()==0){
- throw new XMLException("Schemi non presenti");
- }
- // --------- Creo XSD di root da utilizzare per la validazione ---------
- byte[] schemaPerValidazione = null;
- try{
- StringBuilder bf = new StringBuilder();
- bf.append("<xsd:schema targetNamespace=\"http://openspcoop2.org/validazione_engine\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n");
- StringBuilder bfContenitori = new StringBuilder();
- StringBuilder bfImportNormali = new StringBuilder();
- int indexSystemId = 1;
- for (String targetNamespace : mappingNamespaceLocations.keySet()) {
-
- List<String> splitLocations = mappingNamespaceLocations.get(targetNamespace);
- /*
- * Motivo
- * Perche è stato fatto questo codice sotto ??? : perche' altrimenti la validazione risulta dipendente dall'ordine degli import con stesso namespace.
- * O Meglio il secondo import viene ignorato. Perche? La spiegazione e' in http://stackoverflow.com/questions/4998063/one-xml-namespace-equals-one-and-only-one-schema-file
- * Riassumendo:
- *
- * b1.xsd:
- * <xs:schema targetNamespace="TNS_B" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * ....
- * </xs:schema>
- *
- * b2.xsd:
- * <xs:schema targetNamespace="TNS_B" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * .....
- * </xs:schema>
- *
- * a.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:import namespace="TNS_B" schemaLocation="b1.xsd" />
- * <xs:import namespace="TNS_B" schemaLocation="b2.xsd" />
- * .....
- * </xs:schema>
- *
- * 1) When I ran xmllint --schema a.xsd data.xml, I was presented with this warning:
- * a.xsd:4: element import: Schemas parser warning : Element '{http://www.w3.org/2001/XMLSchema}import':
- * Skipping import of schema located at 'b2.xsd' for the namespace 'TNS_B',
- * since this namespace was already imported with the schema located at 'b1.xsd'.
- * The fact that the import of b2.xsd was skipped obviously leads to this error:
- * a.xsd:9: element attribute: Schemas parser error : DETTAGLIO SULL'ERRORE DELLA VALIDAZIONE FALLITA
- * 2) VisualStudio (XML Spy): work
- *
- * 3) Xerces-J non produce errore in fase di creazione dello schema.
- * Produce pero' lo stesso errore di validazione:
- * a.xsd:9: element attribute: Schemas parser error : DETTAGLIO SULL'ERRORE DELLA VALIDAZIONE FALLITA
- *
- * The crux of the problem here is what does it mean when you have two different <import> elements, when both of them refer to the same namespace.
- * The precise meaning of <import> is a bit fuzzy when you read the W3C spec, possibly deliberately so. As a result, interpretations vary.
- * Some XML processors tolerate multiple <import> for the same namespace, and essentially amalgamate all of the schemaLocation into a single target.
- * Other processors are stricter, and decide that only one <import> per target namespace is valid.
- * I think this is more correct, when you consider that schemaLocation is optional.
- * In addition to the VS and xmllint examples you gave, Xerces-J is also super-strict, and ignores subsequent <import> for the same target namespace,
- * giving much the same error as xmllint does.
- * XML Spy, on the other hand, is much more permissive (but then, XML Spy's validation is notoriously flaky)
- * To be safe, you should not have these multiple imports.
- * A given namespace should have a single "master" document, which in turn has an <include> for each sub-document.
- * This master is often highly artificial, acting only as a container. for these sub-documents.
- * From what I've seen, this generally consists of "best practise" for XML Schema when it comes to maximum tool compatibility,
- * but some will argue that it's a hack that takes away from elegant schema design.
- *
- * CONCLUSIONI:
- * Viene quindi usato l'approccio a contenitore suggerito.
- *
- * openspcoop_system.xsd:
- * <xs:schema targetNamespace="TNS_B" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:include namespace="TNS_B" schemaLocation="b1.xsd" />
- * <xs:include namespace="TNS_B" schemaLocation="b2.xsd" />
- * </xs:schema>
- *
- * a.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:import namespace="TNS_B" schemaLocation="openspcoop_system.xsd" />
- * .....
- * </xs:schema>
- *
- *
- *
- * Inoltre viene applicato un ulteriore accorgimento per superare il seguente problema:
- *
- * types.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * ....
- * </xs:schema>
- *
- * f1.xsd:
- * <xs:schema targetNamespace="TNS_B" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:import namespace="TNS_A" schemaLocation="types.xsd" />
- * .....
- * </xs:schema>
- *
- * f2.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:include namespace="TNS_A" schemaLocation="types.xsd" />
- * .....
- * </xs:schema>
- *
- * root.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:import namespace="TNS_B" schemaLocation="f1.xsd" />
- * <xs:import namespace="TNS_A" schemaLocation="f2.xsd" />
- * </xs:schema>
- *
- * Nonostante sia stato seguito l'approccio a contenitore, durante l'utilizzo del root.xsd schema, si ottiene l'errore:
- * root.xsd:4: element import: Schemas parser warning : Element '{http://www.w3.org/2001/XMLSchema}import':
- * Skipping import of schema located at 'f2.xsd' for the namespace 'TNS_A',
- * since this namespace was already imported with the schema located at 'types.xsd'.
- *
- * Questo perche' importando il file f1.xsd, a sua volta questo importava lo schema types.xsd che definisce lo stesso namespace usato dopo.
- * Se invece si inverte l'import nel file root.xsd tale problema non avviene poiche' al momento di importare f1.xsd,
- * il namespace TNS_A e' gia' stato creato ed il file types.xsd gia' stato importato correttamente (avendo il solito nome di file puo' essere ignorato):
- *
- * root.xsd:
- * <xs:schema targetNamespace="TNS_A" xmlns:xs="http://www.w3.org/2001/XMLSchema">
- * <xs:import namespace="TNS_A" schemaLocation="f2.xsd" />
- * <xs:import namespace="TNS_B" schemaLocation="f1.xsd" />
- * </xs:schema>
- *
- * Soluzione: La classe contenitore conterra' il namespace che viene utilizzato da piu' schemi e li includera'.
- * Dagli schemi inclusi nella classe contenitore vengono esclusi gli schemi che sono inclusi o importati in un altro schema xsd sempre con stesso namespace.
- * Di fatto quindi la classe contenitore conterra' solo le inclusioni degli schemi con stesso namespace che non vengono importati/inclusi da altri.
- * Tali schemi possono poi essere utilizzati anche in altri schemi con differenti namespace come nel caso di esempio sopra riportato.
- * Siccome comunque saranno importati sicuramente anche nella classe contenitore, vengono definiti prima gli import delle classi contenitori e
- * solo dopo gli import 'normali'.
- **/
- if(splitLocations.size()==1){
- bfImportNormali.append("\t<xsd:import namespace=\""+targetNamespace+"\" schemaLocation=\""+splitLocations.get(0)+"\" />\n");
- }
- else{
- String systemIdNewSchema = "System_OpenSPCoop_Id_"+indexSystemId+".xsd";
- indexSystemId++;
- bfContenitori.append("\t<xsd:import namespace=\""+targetNamespace+"\" schemaLocation=\""+systemIdNewSchema+"\" />\n");
- // Creo schema che contiene tutti gli schemi con stesso target namespace e registro la nuova risorsa
- StringBuilder bfStessoNamespace = new StringBuilder();
- bfStessoNamespace.append("<xsd:schema targetNamespace=\""+targetNamespace+"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n");
- for(int i=0;i<splitLocations.size();i++){
- // Devo includere uno schema solo se questo non e' gia' a sua volta incluso o importato da un altro schema con stesso namespace.
- // Altrimenti ottengo un errore simile al seguente:
- // A schema cannot contain two global components with the same name; this schema contains two occurrences of ....
- boolean findImportInclude = false;
- for(int j=0;j<splitLocations.size();j++){
- if(j==i){
- continue; // salto me stesso
- }
- byte [] xsd = resources.get(splitLocations.get(j));
- Document d = this.xmlUtils.newDocument(xsd);
- List<Node> imports = this.readImports(d);
- if(imports!=null){
- for (Node node : imports) {
- if(node!=null){
- String schemaLocation = this.getImportSchemaLocation(node);
- if(schemaLocation!=null){
- //System.out.println("IMPORT: "+schemaLocation);
- String baseLocation = getBaseNameXSDLocation(schemaLocation);
- //System.out.println("IMPORT-BASE: "+baseLocation);
- if(splitLocations.get(i).equals(baseLocation)){
- findImportInclude = true;
- break;
- }
- }
- }
- }
- }
- if(findImportInclude){
- break;
- }
- List<Node> includes = this.readIncludes(d);
- if(includes!=null){
- for (Node node : includes) {
- if(node!=null){
- String schemaLocation = this.getIncludeSchemaLocation(node);
- if(schemaLocation!=null){
- //System.out.println("INCLUDE: "+schemaLocation);
- String baseLocation = getBaseNameXSDLocation(schemaLocation);
- //System.out.println("INCLUDE-BASE: "+baseLocation);
- if(splitLocations.get(i).equals(baseLocation)){
- findImportInclude = true;
- break;
- }
- }
- }
- }
- }
- if(findImportInclude){
- break;
- }
- }
- if(findImportInclude==false)
- bfStessoNamespace.append("\t<xsd:include schemaLocation=\""+splitLocations.get(i)+"\" />\n");
- }
- bfStessoNamespace.append("</xsd:schema>");
- //System.out.println("NUOVA REGISTRAZIONE PER ["+systemIdNewSchema+"] ["+bfStessoNamespace.toString()+"]");
- resources.put(systemIdNewSchema, bfStessoNamespace.toString().getBytes());
- }
- }
- bf.append(bfContenitori.toString());
- bf.append(bfImportNormali.toString());
- bf.append("</xsd:schema>");
- schemaPerValidazione = bf.toString().getBytes();
- //System.out.println("XSD: ["+bf.toString()+"]");
- }catch(Exception e){
- throw new XMLException("Creazione dello schema fallita: "+e.getMessage(),e);
- }
- XSDSchemaCollection collection = new XSDSchemaCollection();
- collection.setSchemaRoot(schemaPerValidazione);
- collection.setResources(resources);
- collection.setMappingNamespaceLocations(mappingNamespaceLocations);
-
- return collection;
- }
-
-
-
-
-
- // UTILITIES GENERICHE
-
- public void registraMappingNamespaceLocations(byte[] resource,String location,Map<String, List<String>> mappingNamespaceLocations) throws XMLException {
- String targetNamespaceXSD = this.getTargetNamespace(resource);
- if(targetNamespaceXSD!=null){
- mappingNamespaceLocations.computeIfAbsent(targetNamespaceXSD, k -> new ArrayList<>())
- .add(location);
- }
- }
-
- public String getBaseNameXSDLocation(String location) throws MalformedURLException{
- if(location.startsWith("http://") || location.startsWith("https://") || location.startsWith("file://")){
- URL url = new URL(location);
- File fileUrl = new File(url.getFile());
- return fileUrl.getName();
- }
- else{
- File f = new File(location);
- return f.getName();
- }
- }
-
- }