Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
jlibs.xml.xsd.XSInliner Maven / Gradle / Ivy
/**
* Copyright 2015 Santhosh Kumar Tekuri
*
* The JLibs authors license this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package jlibs.xml.xsd;
import jlibs.core.io.CharArrayWriter2;
import jlibs.core.lang.ImpossibleException;
import jlibs.core.lang.OS;
import jlibs.core.net.URLUtil;
import jlibs.xml.Namespaces;
import jlibs.xml.sax.SAXDelegate;
import jlibs.xml.sax.SAXUtil;
import jlibs.xml.sax.helpers.MyNamespaceSupport;
import jlibs.xml.xsl.TransformerUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.*;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.util.*;
/**
* @author Santhosh Kumar T
*/
public class XSInliner extends SAXDelegate{
private static final String SCHEMA_LOCATION = "schemaLocation";
private static final String IMPORT = "import";
private String outputSystemID;
private static final List TOP_ELEMS = Arrays.asList(IMPORT, "redefine", "annotation");
public Document inline(InputSource input, String outputSystemID) throws IOException, SAXException, ParserConfigurationException, TransformerConfigurationException{
DOMResult result = new DOMResult();
TransformerHandler handler = TransformerUtil.newTransformerHandler(null, true, 4, null);
setHandler(handler);
handler.setResult(result);
this.outputSystemID = outputSystemID==null ? input.getSystemId() : outputSystemID;
if(this.outputSystemID!=null)
this.outputSystemID = URLUtil.toURL(this.outputSystemID).toString();
parse(input);
Document doc = (Document)result.getNode();
Element root = doc.getDocumentElement();
// get children xs:import, xs:redefine and xs:annotation
NodeList children = root.getChildNodes();
List list = new ArrayList();
for(int i=0; i=0; i--){
Node node = list.get(i);
if(root.getFirstChild()==null)
root.appendChild(node);
else
root.insertBefore(node, root.getFirstChild());
}
return doc;
}
public Document inline(InputSource input) throws IOException, SAXException, ParserConfigurationException, TransformerConfigurationException{
return inline(input, null);
}
private void parse(InputSource source) throws ParserConfigurationException, IOException, SAXException{
SAXParser parser = SAXUtil.newSAXParser(true, false, false);
SAXUtil.setHandler(parser.getXMLReader(), this);
parser.getXMLReader().parse(source);
}
Context mainContext;
Context curContext;
static class Context{
Context parent;
MyNamespaceSupport nsSupport = new MyNamespaceSupport();
String systemID;
String targetNamespace;
int depth;
Context(Context parent, String systemID){
this.parent = parent;
this.systemID = systemID;
}
String resolve(String location){
return URLUtil.resolve(systemID, location).toString();
}
public void setTargetNamespace(String namespace){
targetNamespace = namespace==null ? "" : namespace;
}
}
private String tempSystemID;
@Override
public void setDocumentLocator(Locator locator){
tempSystemID = locator.getSystemId();
}
@Override
public void startDocument() throws SAXException{
curContext = new Context(curContext, tempSystemID);
if(mainContext==null)
mainContext = curContext;
curContext.nsSupport.startDocument();
if(isMainDocument())
super.startDocument();
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException{
curContext.nsSupport.startPrefixMapping(prefix, uri);
if(!isMainDocument()){
if(mainContext.nsSupport.findPrefix(uri)!=null)
return;
prefix = mainContext.nsSupport.startPrefixMapping(uri);
if(curContext.depth==0)
return;
}
super.startPrefixMapping(prefix, uri);
}
private static final List QNAME_ATTS = Arrays.asList("type", "ref", "base");
private Set included = new HashSet();
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException{
curContext.depth++;
curContext.nsSupport.startElement();
Enumeration declaredPrefixes = mainContext.nsSupport.getDeclaredPrefixes();
if(!isMainDocument())
mainContext.nsSupport.startElement();
if(isInclude(uri, localName)){
try{
InputSource importSource = null;
String location = curContext.resolve(atts.getValue(SCHEMA_LOCATION));
String importElem = "<"+qName+" schemaLocation=\""+atts.getValue(SCHEMA_LOCATION)+"\">";
comment(importElem.toCharArray(), 0, importElem.length());
if(!included.add(location))
return;
EntityResolver resolver = getEntityResolver();
if(resolver!=null)
importSource = resolver.resolveEntity(null, location);
if(importSource==null)
importSource = new InputSource(location);
parse(importSource);
return;
}catch(Exception ex){
if(ex instanceof SAXException)
throw (SAXException)ex;
throw new SAXException(ex);
}
}
if(isRoot(uri, localName)){
curContext.setTargetNamespace(atts.getValue("targetNamespace"));
if(isMainDocument() && !mainContext.targetNamespace.isEmpty()){
if(mainContext.nsSupport.findPrefix(mainContext.targetNamespace)==null){
String prefix = mainContext.nsSupport.declarePrefix(mainContext.targetNamespace);
super.startPrefixMapping(prefix, mainContext.targetNamespace);
}
}
}
if(isMainDocument()){
if(isImport(uri, localName) && atts.getValue(SCHEMA_LOCATION)!=null){
AttributesImpl newAtts = new AttributesImpl(atts);
String attValue = atts.getValue(SCHEMA_LOCATION);
String location = curContext.resolve(attValue);
attValue = URLUtil.relativize(outputSystemID, location).toString();
newAtts.setValue(atts.getIndex(SCHEMA_LOCATION), attValue);
atts = newAtts;
}
}else{
if(isRoot(uri, localName))
return;
qName = mainContext.nsSupport.toQName(uri, localName);
AttributesImpl newAtts = new AttributesImpl();
for(int i=0; i";
comment(importElem.toCharArray(), 0, importElem.length());
return;
}
if(!isMainDocument()){
if(isRoot(uri, localName))
return;
qName = mainContext.nsSupport.toQName(uri, localName);
}
super.endElement(uri, localName, qName);
if(!isMainDocument() && curContext.depth==1){
Enumeration declaredPrefixes = mainContext.nsSupport.getDeclaredPrefixes();
while(declaredPrefixes.hasMoreElements()){
String prefix = declaredPrefixes.nextElement();
super.endPrefixMapping(prefix);
}
}
}
@Override
public void endPrefixMapping(String prefix) throws SAXException{
if(isMainDocument())
super.endPrefixMapping(prefix);
}
@Override
public void endDocument() throws SAXException{
if(isMainDocument())
super.endDocument();
curContext = curContext.parent;
}
private boolean isMainDocument(){
return curContext==mainContext;
}
private boolean isRoot(String uri, String localName){
return Namespaces.URI_XSD.equals(uri) && "schema".equals(localName);
}
private boolean isInclude(String uri, String localName){
return Namespaces.URI_XSD.equals(uri) && "include".equals(localName);
}
private boolean isImport(String uri, String localName){
return Namespaces.URI_XSD.equals(uri) && IMPORT.equals(localName);
}
public static InputSource include(String targetNamespace, String... systemIDs) throws TransformerConfigurationException{
CharArrayWriter2 writer = new CharArrayWriter2();
XSDocument doc = new XSDocument(new StreamResult(writer), true, 4, null);
try{
doc.startDocument();
doc.startSchema(targetNamespace);
for(String systemID: systemIDs)
doc.addInclude(URLUtil.toURL(systemID).toString());
doc.endSchema();
doc.endDocument();
}catch(SAXException ex){
throw new ImpossibleException(ex);
}
return new InputSource(writer.toCharSequence().asReader());
}
public static void main(String[] args) throws Exception{
if(args.length==0){
System.err.println("Usage:");
System.err.println("\txsd-inline."+(OS.get().isWindows()?"bat":"sh")+" ");
System.err.println("\txsd-inline."+(OS.get().isWindows()?"bat":"sh")+" ...");
System.exit(1);
}
InputSource source;
if(args.length==1)
source = new InputSource(args[0]);
else{
String targetNamespace = args[0];
String xsdFiles[] = Arrays.copyOfRange(args, 1, args.length);
source = XSInliner.include(targetNamespace, xsdFiles);
}
Document doc = new XSInliner().inline(source, "temp.xsd");
TransformerUtil.newTransformer(null, true, 0, null)
.transform(new DOMSource(doc), new StreamResult(System.out));
System.out.println();
}
}