在定期更新的XSD中替换xsd:choice

时间:2018-11-21 10:47:22

标签: xml xslt xsd

是否有一种简单的(XSLT?)(最好是自动化的)方法,可以将XSD文件中的xsd:choice构造更改为没有选择构造的定义。例如,我得到一个包含以下部分的XSD:

<xsd:choice minOccurs="1" maxOccurs="1">
   <xsd:element name="ExistingBuild" type="ExistingBuild" nillable="false"/>
   <xsd:element name="NewBuild" type="NewBuild" nillable="false"/>
</xsd:choice>

此XSD需要导入不支持选择构造的应用程序中。我已经手动更改了XSD,以将段定义如下:

<xsd:element name="ExistingBuild" type="ExistingBuild" nillable="false" minOccurs="0" maxOccurs="1"/>
<xsd:element name="NewBuild" type="NewBuild" nillable="false" minOccurs="0" maxOccurs="1"/>

生成的XSD可以正确导入并达到目的。因此,我可以手动更改此设置。

但是,该XSD将来会定期更新,我需要在每次发布新版本时手动对其进行更改。为了防止人为错误,我希望自动执行此转换。 XSLT是否可以解决此问题,我将如何定义这样的XSLT解决方案?

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

编写XSLT删除xsd:choice元素并不难

从身份模板开始(该模板处理您不想更新的内容)

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

添加模板以忽略xsd:choice

<xsl:template match="xsd:choice">
  <xsl:apply-templates />
</xsl:template>

然后添加一个模板来处理子xsd:elements

<xsl:template match="xsd:choice/xsd:element">
  <xsd:element minOccurs="0" maxOccurs="{../@maxOccurs}">
    <xsl:apply-templates select="@*" />
  </xsd:element>
</xsl:template>

将所有内容放在一起就可以得到...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsd="https://www.w3.org/2001/XMLSchema"
                version="1.0">
  <xsl:output method="xml" indent="yes" />

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

  <xsl:template match="xsd:choice">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="xsd:choice/xsd:element">
    <xsd:element minOccurs="0" maxOccurs="{../@maxOccurs}">
      <xsl:apply-templates select="@*" />
    </xsd:element>
  </xsl:template>
</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/bFDb2Di上以不完整的架构查看实际运行情况