我正在处理一个处理某些XSD的样式表。 主XSD文件包括另外2个。其中2个还包括另一个。 所有XSD在根元素中具有相同的属性和名称空间。这些文件仅用于维护目的。
样式表:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:exa="http://www.example.com/"
exclude-result-prefixes="xsl xs exa">
<xsl:output method="xml" indent="yes" encoding="iso-8859-1" />
<!-- global variable to merge schema with it's includes
to be used for further processing the schema -->
<xsl:variable name="with_includes">
<xsl:apply-templates select="/xs:schema" mode="include"/>
</xsl:variable>
<!-- copy the main schema root element including attributes
then process all nodes in it -->
<xsl:template match="xs:schema" mode="include">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()" mode="include"/>
</xsl:copy>
</xsl:template>
<!-- all schemas have the same namespaces and targetnamespace defined
so do not copy namespaces -->
<xsl:template match="node()" mode="include">
<xsl:copy-of select="." copy-namespaces="no"/>
</xsl:template>
<!-- when matching an include, process all the nodes in the schema -->
<xsl:template match="xs:include" mode="include">
<xsl:apply-templates select="doc(@schemaLocation)/xs:schema/node()" mode="include"/>
</xsl:template>
<!-- only here to show the result -->
<xsl:template match="/xs:schema">
<xsl:copy-of select="$with_includes"/>
</xsl:template>
</xsl:stylesheet>
一些非常基本的示例模式来演示这个问题:
Schema A.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/example"
xmlns:exa="http://www.example.com/example">
<xs:include schemaLocation="B.xsd"/>
<xs:include schemaLocation="C.xsd"/>
<xs:element name="a" type="exa:t_a"/>
<xs:complexType name="t_a">
<xs:sequence>
<xs:element name="b" type="exa:t_b"/>
<xs:element name="c" type="exa:t_c"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Schema B.xsd:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/example"
xmlns:exa="http://www.example.com/example">
<xs:include schemaLocation="C.xsd"/>
<xs:complexType name="t_b">
<xs:sequence>
<xs:element name="c1" type="exa:t_c"/>
<xs:element name="c2" type="exa:t_c"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
架构C.xsd
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/example"
xmlns:exa="http://www.example.com/example">
<xs:simpleType name="t_c">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
如果我使用上面的样式表,我会在结果中得到simpleType t_c两次。我正在寻找一种方法来防止这种情况。
是的,我使用撒克逊人。答案 0 :(得分:4)
对包含进行重复数据删除相对简单,但如果您需要处理周期则会变得更加复杂 - 在XSD中允许使用xs:includes的循环,尽管1.0规范并不完全清楚。如果您不关心周期,只需使用递归函数通过传递扩展构建所有包含的列表,最好调用resolve-uri()以针对其基URI解析每个@schemaLocation,然后从列表中删除重复项使用distinct-values()。如果需要消除循环,则需要将参数传递给递归函数,指示到达文档的路径,如果文档已经在列表中,则忽略该文档。如果您有我的书的副本,那么在xsl:call-template的部分中有一个循环检测示例。但你也可能觉得这本书太贵了; - (