java - Create XSD based on root element -
i have xsd shown below , need extract root elements in xsd , create separate xsd each root element pragmatically in java, there framework of java library can aid me in achieving this.
<?xml version='1.0' encoding='windows-1252'?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <xsd:complextype name="usaddress"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:string"/> </xsd:sequence> </xsd:complextype> <xsd:complextype name="ordertype"> <xsd:sequence> <xsd:element name="orderid" type="xsd:string"/> <xsd:element name="billto" type="usaddress"/> </xsd:sequence> </xsd:complextype> <xsd:element name="customer"> <xsd:complextype> <xsd:sequence> <xsd:element name="customerid" type="xsd:string"/> <xsd:element name="address" type="usaddress"/> </xsd:sequence> </xsd:complextype> </xsd:element> <xsd:element name="order" type="ordertype"/> </xsd:schema> to
<?xml version='1.0' encoding='windows-1252'?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <xsd:complextype name="usaddress"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:string"/> </xsd:sequence> </xsd:complextype> <xsd:complextype name="ordertype"> <xsd:sequence> <xsd:element name="orderid" type="xsd:string"/> <xsd:element name="billto" type="usaddress"/> </xsd:sequence> </xsd:complextype> <xsd:element name="order" type="ordertype"/> </xsd:schema> <?xml version='1.0' encoding='windows-1252'?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <xsd:complextype name="usaddress"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:string"/> </xsd:sequence> </xsd:complextype> <xsd:element name="customer"> <xsd:complextype> <xsd:sequence> <xsd:element name="customerid" type="xsd:string"/> <xsd:element name="address" type="usaddress"/> </xsd:sequence> </xsd:complextype> </xsd:element> </xsd:schema>
using xsl 2.0 can have multiple output documents , can define every file name, file content, etc. default java support xsl 2.0 far perfect, use incredible saxon (you can download saxon-he here, unzip , add saxon9he.jar project).
this example xsl 2.0 i've made, works using idea user laune has exposed in his comment. produces 1 output schema every element, , schema not element (types). every new schema contains xs:element's , has xs:include including schema containing types. quite simple (and clever in opinion) method , easy understand if you're familiar xsl (look @ xsl comments).
xsl.xsl
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="2.0"> <xsl:template match="/"> <xsl:for-each select="/*/*[local-name()='element']"> <xsl:variable name="currentelement" select="."/> <!-- create schema every element containing element, including types schema --> <xsl:result-document method="xml" href="schema_element_{@name}.xsd"> <xsl:for-each select="/*[1]"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:element name="include" namespace="http://www.w3.org/2001/xmlschema"> <xsl:attribute name="schemalocation">schema_types.xsd</xsl:attribute> </xsl:element> <!-- include clause --> <xsl:copy-of select="$currentelement"/> <!-- content current xs:element --> </xsl:copy> </xsl:for-each> </xsl:result-document> </xsl:for-each> <xsl:for-each select="/*[1]"> <!-- create types document containing root xs:element's --> <xsl:result-document method="xml" href="schema_types.xsd"> <xsl:copy> <xsl:copy-of select="@*"/> <xsl:copy-of select="node()[local-name()!='element']"/> </xsl:copy> </xsl:result-document> </xsl:for-each> </xsl:template> </xsl:stylesheet> the java code needed calling saxon xsl transformation produce output files names dynamically derived in xsl.
main.java
import java.io.file; import javax.xml.transform.transformer; import javax.xml.transform.transformerfactory; import javax.xml.transform.stream.streamresult; import javax.xml.transform.stream.streamsource; public class main { public static void main(string[]args) throws exception{ transformerfactory tfactory = transformerfactory.newinstance(); transformer transformer = tfactory.newtransformer(new streamsource(new file("xsl.xsl"))); transformer.transform(new streamsource(new file("schema.xsd")), new streamresult(system.out)); } } using example schema, xsl , running java code these files created these filenames (note indentation might lost):
schema_element_customer.xsd
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <include xmlns="http://www.w3.org/2001/xmlschema" schemalocation="schema_types.xsd" /> <xsd:element name="customer"> <xsd:complextype> <xsd:sequence> <xsd:element name="customerid" type="xsd:string" /> <xsd:element name="address" type="usaddress" /> </xsd:sequence> </xsd:complextype> </xsd:element> </xsd:schema> schema_element_order.xsd
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <include xmlns="http://www.w3.org/2001/xmlschema" schemalocation="schema_types.xsd" /> <xsd:element name="order" type="ordertype" /> </xsd:schema> schema_types.xsd
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns="http://www.example.org" targetnamespace="http://www.example.org" elementformdefault="qualified"> <xsd:complextype name="usaddress"> <xsd:sequence> <xsd:element name="housenumber" type="xsd:string" /> </xsd:sequence> </xsd:complextype> <xsd:complextype name="ordertype"> <xsd:sequence> <xsd:element name="orderid" type="xsd:string" /> <xsd:element name="billto" type="usaddress" /> </xsd:sequence> </xsd:complextype> </xsd:schema> update: necessary changes output map
necessary changes output map instead of files in file-system:
based on this answer realized can add setting notified every result-document can writte output want implementing outputuriresolver. i've made 1 writes hashmap:
import java.io.stringwriter; import java.util.map; import javax.xml.transform.result; import javax.xml.transform.transformerexception; import javax.xml.transform.stream.streamresult; import net.sf.saxon.lib.outputuriresolver; public class hashmapsaveroutputuriresolver implements outputuriresolver{ private map<string, string> results; // save here public hashmapsaveroutputuriresolver(map<string, string> map){ this.results = map; // set map } public outputuriresolver newinstance() { return this; } public result resolve(string href, string base) throws transformerexception { // set resolve file write stringresult wraps stringwritter stringwriter sw = new stringwriter(); // stringwritter streamresult sr = new streamresult(sw); // streamresult sr.setsystemid(href); // id of streamresult = href = filename return sr; } public void close(result result) throws transformerexception { // end of result:document transformed streamresult sr = (streamresult) result; // streamresult stringwriter sw = (stringwriter) sr.getwriter(); // streamwritter string href = sr.getsystemid(); // href (filename) string content = sw.tostring(); // string file-content this.results.put(href, content); // save in map } } in main file need add 2 new lines (create map, , set proper setting outputuriresolver associated map).
public static void main(string[] args) throws exception { hashmap<string, string> results = new hashmap<string, string>(); // map transformerfactory tfactory = transformerfactory.newinstance(); tfactory.setattribute("http://saxon.sf.net/feature/outputuriresolver", new hashmapsaveroutputuriresolver(results)); // set outputuriresolver transformer transformer = tfactory.newtransformer(new streamsource(new file("xsl.xsl"))); transformer.transform(new streamsource(new file("schema.xsd")), new streamresult(system.out)); // once transformation has finished map filled }
Comments
Post a Comment