使用xslt转换多个xml模式文档



我有许多xml模式文档,用于描述我的应用程序的配置设置。xml模式看起来像以下几行:

Client.xsd

<xsd:schema targetNamespace="http://www.example.com/network"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="Client">
        <xsd:attribute name="Host" type="xsd:string>
    </xsd:complexType>
</xsd:schema>

Server.xsd

<xsd:schema targetNamespace="http://www.example.com/network"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="Server">
        <xsd:attribute name="Port" type="xsd:unsignedShort>
        <xsd:attribute name="MaxConnections" type="xsd:int default="32">
    </xsd:complexType>
</xsd:schema>

Application.xsd

<xsd:schema targetNamespace="http://www.example.com/core"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="Application">
        <xsd:attribute name="Name" type="xsd:string>
        <xsd:attribute name="Id" type="xsd:int>
    </xsd:complexType>
</xsd:schema>

FooClient.xsd

<xsd:schema targetNamespace="http://www.example.com/foo"
            xmlns:core="network://www.example.com/network"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="http://www.example.com/network"
                schemaLocation="client.xsd"/>
    <xsd:complexType name="FooClient">
        <xsd:complexContent>
            <xsd:extension base="network:Client">
                <xsd:attribute name="foo" type="xsd:string"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

FooServer.xsd

<xsd:schema targetNamespace="http://www.example.com/foo"
            xmlns:core="network://www.example.com/network"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="http://www.example.com/network"
                schemaLocation="client.xsd"/>
    <xsd:complexType name="FooServer">
        <xsd:complexContent>
            <xsd:extension base="network:Server">
                <xsd:attribute name="foo" type="xsd:string"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

FooApplication.xsd

<xsd:schema targetNamespace="http://www.example.com/foo"
            xmlns:core="http://www.example.com/core"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:import namespace="http://www.example.com/core"
                schemaLocation="Application.xsd"/>
    <xsd:include schemaLocation="FooClient.xsd"/>
    <xsd:include schemaLocation="FooServer.xsd"/>
    <xsd:complexType name="FooApplication">
        <xsd:complexContent>
            <xsd:extension base="core:Application">
                <xsd:sequence>
                    <xsd:element name="FooInput" type="FooClient"/>
                    <xsd:element name="FooOutput" type="FooServer"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:element name="Foo" type="FooApplication"/>
</xsd:schema>

这是一个实例文档的例子:

<foo:Foo xmlns:foo="http://www.example.com/foo" 
         Id="1234"
         Name="FooInstance1">
    <FooInput Host="localhost:12345"
              Name="Input"
              foo="bar"/>
    <FooOutput Port="54321"
               Name="Output"
               foo="bar"/>
</foo:Foo>

我的目标是采用FooApplication模式文档并将其转换为人类可读的形式,以便负责维护应用程序的人员确切地知道可用的配置选项,数据类型,默认值等。最后,我将添加文档元素,这些元素也可以添加到输出中,但现在我试图保持简单。所以上面的例子看起来像这样:

FooApplication/Id, int
FooApplication/Name, string
FooApplication/FooInput/Host, string
FooApplication/FooInput/foo, string
FooApplication/FooOutput/Port, unsignedShort
FooApplication/FooOutput/MaxConnections, int, default=32
FooApplication/FooOutput/foo, string

对于这项任务,xslt似乎是一个显而易见的工具。然而,我很难理解如何从多个文档中提取数据。我尝试了这样的东西(例如索引complexType的所有元素):

<xsl:template match="xsd:include">
    <xsl:apply-templates select="document(@schemaLocation)"/>
</xsl:template>
<xsl:template match="xsd:import">
    <xsl:apply-templates select="document(@schemaLocation)"/>
</xsl:template>
<xsl:key name="complexType" match="xsd:complexType" use="@name"/>

然而,当使用键时,只有来自fooapplication的complexType。解析XSD

有没有人对如何实现这一目标有任何见解?

提前感谢。

我将首先看一下DocFlex,看看它们处理XML Schema文档的方法对您是否有意义。然后你应该能够扩大或缩小规模。对于任何无关紧要的事情,如果您必须构建自己的文档系统,我认为它应该基于XML模式对象模型API (XSOM),用它创建可以使用XSLT呈现的XML……

您不需要以任何方式处理模式,除非将模式编写得更好。

在允许xs:annotation存在的地方尽量使用xs:annotation元素及其子元素xs:documentation

然后你可以使用一个好的XML编辑器,如Visual Studio XML编辑器和IDE的智能感知自动创建模式的实例:

  • 显示注释(描述含义和类型)。
  • 提示/枚举元素可能的属性名称和值以及可能的子元素。对于所有这些,当选择时(在按Enter之前),它们各自的注释也由智能感知显示。

XML编辑器还用红色的笔画标记任何错误,errors窗口显示任何错误或警告消息——当用户输入XML文档时,所有这些都是实时的。

最后:如果在创建注释之后仍然希望生成类似于单独的(甚至是打印的)文档的东西,那么可以轻松地使用XSLT处理模式,只输出可用的注释。

xsl:key不起作用的原因是它只在单个文档中搜索。解决方案可能是创建一个复合文档(在xsl:variable中),合并不同模式文档的内容,然后在其上使用xsl:key。

(或者使用Saxon-EE,它会在需要的地方自动创建索引,避免需要显式键。)

一般来说,使用XSLT操作原始模式文档是困难的,因为在XSD中有许多不同的方法来编写相同的内容。但是,如果您可以控制模式文档中使用的编码风格,则很有可能实现。

感谢Petru Gardea提到我们的工具 DocFlex/XML XSDDoc !

是的,确实,使用我们的XML模式docgen,可以将最初问题中提到的所有示例XML模式记录在一起。

这是我刚刚用他们生成的一个文档:

http://www.filigris.com/pr/stackoverflow.com/questions/8369677/using-xslt-to-transform-multiple-xml-schema-documents/xsddoc/

但是我不得不说所提供的XSD清单有些不正确。如果从字面上理解这些文本并从它们创建相应的XSD文件,那么什么都行不通!(为了生成文档,我需要纠正它们)

首先,某些模式中的XML标记是完全无效的(例如在Application.xsd中)。

其次,FooApplication。XSD使用了不正确的类型引用。它用'FooClient'和'FooServer'对应的类型定义了'FooInput'和'FooOutput'元素。这些类型在FooClient中定义。xsd和FooServer。它们包含在FooApplication.xsd中。这很好。这里缺少的是,这些类型是在名称空间"http://www.example.com/foo"中定义的。但是XML位于FooApplication中。在Xsd中,它们被绑定到不同的名称空间——默认名称空间(即没有名称空间)。因此,声明:

<xsd:element name="FooInput" type="FooClient"/>

实际上不是指类型:

{http://www.example.com/foo}:FooClient

而不是类型:

{no namespace}:FooClient

要使类型引用正确,需要在中再添加一个名称空间绑定在FooApplication.xsd:

<xsd:schema targetNamespace="http://www.example.com/foo"
        xmlns="http://www.example.com/foo"
        xmlns:core="http://www.example.com/core"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">

或使用绑定到"http://www.example.com/foo"的附加名称空间前缀。

因此,如果您曾经尝试使用我们的工具DocFlex/XML XSDDoc直接记录您的原始模式,显然您将没有收到正确的文档!

我们的XML模式doc-gen不会自动验证任何XML模式。它根本做不到,因为,首先,这不是它的工作,其次,任何模式验证都会花费额外的处理时间,这可能会让大多数确信自己的模式是正确的人感到恼火。毕竟,您总是可以在构建文件中添加一些额外的模式验证步骤)

最后,如果上面所说的一切都与您无关——也就是说,示例模式中的所有错误都只是这个特定问题的不准确——那么听到为什么我们的工具不适合您的任务(除了任何商业、财务或组织问题)将是非常有趣的。

Petru Gardea建议我们的解决方案可以"按比例放大"。但总的来说,在什么方向上,它可能需要扩大规模呢?听起来一定很有趣!因为这正是我们自己所关心的——如何使我们的工具文档XML模式变得更好。

注:这个网站上还有一个问题,也和这个话题非常相关:

如何将xsd转换为人类可读的文档?

我也提供了一个答案(尽管有些人可能认为这是一个有争议的答案,特别是从主流观点来看)。遗憾的是,我当时没有这个账户,所以我不能直接联系它。

最新更新