如何引用同一 WSDL 文件中定义的架构?

How do I reference a schema defined in the same WSDL file?

我得到了一个 wsdl 文件,它为同一个命名空间定义了两个模式,如下所示:

<wsdl:types>
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/payments"
                attributeFormDefault="unqualified" elementFormDefault="qualified"
                targetNamespace="http://example.com/payments">
        <xsd:complexType name="TestType">
            <xsd:sequence>
                <xsd:element name="Version" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:schema>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/payments"
                attributeFormDefault="unqualified" elementFormDefault="qualified"
                targetNamespace="http://example.com/payments">
        <xsd:element name="TestRequest">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="Header" type="TestType"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
</wsdl:types>

果然 TestType 无法从 TestRequest 引用。我发现了几个 answers 显示了如何通过 xsd:include 对不同的文件执行此操作(因为我使用的是相同的 targetNamespace),但我不知所措在如何给schemaLocation包括?

请注意,这不是我应该做的事情不是问题。我知道如果我将元素定义移动到相同的架构定义中,问题就会消失。

WSDL 本身不是 XSD 模式语言,因此要通过 xs:include 从 XSD 文件中引用它,您必须摆脱周围的 wsdl:types并且您必须将两个模式存储在单独的文件中(或者,因为它们无论如何都在同一个命名空间中,只需删除额外的 xsd:schema 元素,而不是其内容)。

您可以使用简单的 XSLT 来做到这一点(为简洁起见删除了根注释,确保声明相关的命名空间):

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

<xsl:template match="wsdl:types">
    <xsl:apply-templates select="xsd:schema[1]" />
</xsl:template>

<xsl:template match="xsd:schema">
    <xsl:copy>
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
        <xsl:apply-templates select="following-sibling::xsd:schema/*" />
    </xsl:copy>
</xsl:template>

如果这是一次性任务,那么您可以针对您的 WSDL 简单地 运行 这一次,保存结果并通过相关文件 URI 引用它们。如果您需要更频繁地执行此操作,您应该将其自动化。

对于嵌入在 WSDL 中的 XSD,考虑到您在问题中链接的答案,情况与您所看到的有所不同。

简答:

  • 一个 无法在嵌套在 WSDL 类型部分中的模式之间创建 xsd:include 引用

  • xsd:大多数 WSDL 处理器都支持导入。但是,您 提供 schemaLocation 属性。实际上,它创建了一个悬空模式引用,WSDL 本身的行为类似于 XML 目录。

没有标准方法可以指向任意 XML 文件中的模式(除了 .XSD 文件格式,其中整个文件仅用于一个模式)。当然,XPointer 或类似的东西可能有用;但似乎没有人在 XSD 或 WSDL 处理器中为此实施解决方案。

具有相同命名空间的架构无法正常工作这一事实表明 WSDL 处理器的实现存在局限性。应该没有理由解决悬空导入问题,但没有理由解决带有目标命名空间 的模式。后一个亮点的原因是可以包含没有命名空间的模式and/or导入,这会导致歧义。