使用XSLT在XML Schema中删除多余的复杂类型

时间:2014-11-04 21:05:49

标签: xslt xsd

我收到了一组XML Schema,其中包含"多余的"复杂的类型,我正在寻找一种使用XSLT删除它们的方法。

模式(见下文)有许多<xsd:element name="ElementX" type="ComplexTypeX">个标签,每个标签都引用一个复杂的类型。每个复杂类型都继承自另一个模式(Datatypes.xsd)中的基类型,但是不会扩展或限制类型 - 因此没有多大意义!

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema targetNamespace="..." xmlns:xsd="..." xmlns="...">
  <xsd:include schemaLocation="Datatypes.xsd" />

  <xsd:complexType name="ComplexType1">
    <xsd:simpleContent>
      <xsd:extension base="ActualType1" />
    </xsd:simpleContent>
  </xsd:complexType>
  <xsd:element name="ElementName1" type="ComplexType1" />

  <xsd:complexType name="ComplexType2">
    <xsd:simpleContent>
      <xsd:extension base="ActualType2" />
    </xsd:simpleContent>
  </xsd:complexType>
  <xsd:element name="ElementName2" type="ComplexType2" />

  ...
 </xsd:schema>

我尝试(但不是很远......)将XSLT转换写入:

  • 用相应的复杂类型的基本类型替换每个元素的类型。例如。上面的ElementName1的类型将变为ActualType1。

  • 从输出中删除整个complexType。

制作输出:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema targetNamespace="..." xmlns:xsd="..." xmlns="...">
  <xsd:include schemaLocation="Datatypes.xsd" />

  <xsd:element name="ElementName1" type="ActualType1" />

  <xsd:element name="ElementName2" type="ActualType2" />
  .
  .
  .
 </xsd:schema>

目前,所有complexType元素都不会以任何方式更改基本类型,因此可以安全地执行替换。但是,如果将来某些complexType元素被更改为限制或扩展其基类型(并且具有有意义的用途),我只想执行替换/删除剩余的多余类型。虽然我意识到这会在某种程度上增加XSLT的复杂性。

背景:这些模式来自第三方,不幸的是我无法控制他们的产品。我怀疑由于用于生成模式的工具而存在额外的复杂类型层。

谢谢!

2 个答案:

答案 0 :(得分:1)

  

我正在尝试(但不是很远......)编写XSLT转换   致:

     
      
  • 用相应的复杂类型的基本类型替换每个元素的类型。例如。上面的ElementName1的类型将成为   ActualType1。

  •   
  • 从输出中删除整个complexType。

  •   

这两个可以通过以下方式实现:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="complex" match="xsd:complexType" use="@name" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- replace element type -->
<xsl:template match="xsd:element">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:attribute name="type">
            <xsl:value-of select="key('complex', @type)/xsd:simpleContent/xsd:extension/@base"/>
        </xsl:attribute>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

<!-- remove complexType -->
<xsl:template match="xsd:complexType"/>

</xsl:stylesheet>

恐怕我不明白这一部分:

  

但是在某些complexType元素被更改为的情况下   限制或扩展他们的基本类型(并有一些有意义的用途),我   我希望在执行之前添加一个检查   更换/移除。

答案 1 :(得分:1)

你似乎想要这样的东西:

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <!-- anything not otherwise matched gets copied -->

  <xsl:template match="@*|node()">
    <xsl:apply-templates select="." mode="literal"/>
  </xsl:template>

  <xsl:template match="@*|node()" mode="attribute-filter">
    <xsl:apply-templates select="." mode="literal"/>
  </xsl:template>

  <xsl:template match="@*|node()" mode="literal">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- in mode 'attribute-filter', 'name' and 'type' attributes transform to nothing -->
  <xsl:template match="@name|@type" mode="attribute-filter">
    <!-- transforms to nothing -->
  </xsl:template>

  <!-- keep only meaningful extension types -->
  <xsl:template match="/xsd:schema/xsd:complexType[./xsd:simpleContent/xsd:extension]">
    <xsl:if test="boolean(./xsd:simpleContent/xsd:extension/node())">
      <!-- a bona fide extension -->
      <xsl:apply-templates select="." mode="literal"/>
    </xsl:if>
    <!-- else it transforms to nothing -->
  </xsl:template>

  <!-- patch up element declarations where necessary -->
  <xsl:template match="xsd:element[@type]">
    <xsl:variable name="typename" select="@type" />
    <xsl:choose>
      <xsl:when test="not(/xsd:schema/xsd:complexType[@name = $typename]/xsd:simpleContent)">
        <xsl:apply-templates select="." mode="literal"/>
      </xsl:when>
      <xsl:when test="boolean(/xsd:schema/xsd:complexType[@name = $typename]/xsd:simpleContent/xsd:restriction)">
        <xsl:apply-templates select="." mode="literal"/>
      </xsl:when>
      <xsl:when test="boolean(/xsd:schema/xsd:complexType[@name = $typename]/xsd:simpleContent/xsd:extension/node())">
        <xsl:apply-templates select="." mode="literal"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="xsd:element">
          <xsl:copy-of select="@name" />
          <xsl:attribute name="type">
            <xsl:value-of select="/xsd:schema/xsd:complexType[@name = $typename]/xsd:simpleContent/xsd:extension/@base"/>
          </xsl:attribute>
          <xsl:apply-templates select="@*|node()" mode="attribute-filter"/>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

假设不需要的complexType声明都使用简单内容的“扩展”替代方法,如示例所示,但它也可以扩展为也处理其他不需要的类型。