我有一个如下所示的XSD,我需要提取XSD中的所有根元素,并在java中以实际方式为每个根元素创建一个单独的XSD,是否有一些java库框架可以帮助我实现这一点。
<?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>
答案 0 :(得分:2)
使用 XSL 2.0 ,您可以拥有多个输出文档,并可以定义每个文件名,文件内容等。默认 java 支持 XSL 2.0 远非完美,所以我使用了令人难以置信的 Saxon (你可以下载 saxon-he here,解压缩并添加 saxon9he.jar 到您的项目中。)
这是我所做的XSL 2.0示例,它使用用户laune在his comment中公开的想法。因此它为每个元素生成一个输出模式,并为非元素(类型)的所有内容生成模式。每个新架构仅包含 xs:element ,并且具有 xs:include ,包括包含类型的架构。如果您熟悉XSL(查看xsl注释),这是一个非常简单(在我看来非常聪明)的方法,并且易于理解。
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 for every element containing only 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"/> <!-- Only content is current xs:element -->
</xsl:copy>
</xsl:for-each>
</xsl:result-document>
</xsl:for-each>
<xsl:for-each select="/*[1]">
<!-- Create types document containing all but 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>
所需的唯一java代码是调用 saxon 进行xsl转换,生成输出文件,其名称在 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));
}
}
使用您的示例模式,我的xsl并运行java代码,这些是使用这些文件名创建的文件(请注意,缩进可能会丢失):
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>
必须更改输出到Map而不是文件系统中的文件:
基于this answer我意识到您可以添加一个设置以供每个结果文档通知,以便您可以将输出写入要实现OutputUriResolver的位置。所以我已经写了一个写入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; // We 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 { // We set to resolve the file to write to a stringResult that wraps a stringWritter
StringWriter sw = new StringWriter(); // StringWritter
StreamResult sr = new StreamResult(sw); // StreamResult
sr.setSystemId(href); // Id of the streamResult = href = fileName
return sr;
}
public void close(Result result) throws TransformerException { // End of result:document transformed
StreamResult sr = (StreamResult) result; // Get StreamResult
StringWriter sw = (StringWriter) sr.getWriter(); // Get StreamWritter
String href = sr.getSystemId(); // Get href (fileName)
String content = sw.toString(); // Get string file-content
this.results.put(href, content); // Save in map
}
}
在主文件中,您只需添加两个新行(创建地图,并将正确的设置设置为与地图关联的OutputUriResolver)。
public static void main(String[] args) throws Exception {
HashMap<String, String> results = new HashMap<String, String>(); // Your 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 the transformation has finished the Map is filled
}