使用xslt转换多个xml架构文档

时间:2011-12-03 17:55:22

标签: xml xslt xsd

我有许多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"/>

但是,使用密钥时,只解析FooApplicaiton.xsd中的complexType。

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

非常感谢提前。

4 个答案:

答案 0 :(得分:0)

除了更好地编写模式之外,您不需要以任何方式处理模式。

尽可能在允许xs:annotation 的任何地方使用xs:documentation元素及其子xs:annotation

然后,您可以使用良好的XML编辑器(如Visual Studio XML编辑器)和IDE的智能感知器自动创建架构实例:

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

XML编辑器还会使用红色波形标记任何错误,并且“错误”窗口会在用户输入XML文档时实时显示任何错误或警告消息。

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

答案 1 :(得分:0)

首先看一下DocFlex,看看他们对XML Schema文档的处理方法是否合理。然后,您应该可以向上或向下扩展。对于任何微不足道的事情,如果您必须构建自己的doc系统,我认为它应该基于XML Schema Object Model API(XSOM),然后创建XML然后可以使用XSLT ... < / p>

答案 2 :(得分:0)

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

(或者使用Saxon-EE,它将根据需要自动创建索引,避免使用显式键。)

通常,使用XSLT操作原始模式文档很困难,因为在XSD中编写相同内容的方法有很多种。但是,如果您可以控制架构文档中使用的编码样式,则很有可能实现。

答案 3 :(得分:0)

谢谢,Petru Gardea,提及我们的工具 的 DocFlex/XML XSDDoc

是的,使用我们的XML模式doc-gen,可以将初始问题中提到的所有示例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.xsd中定义,它们包含在FooApplication.xsd中。没关系。 这里缺少的是那些类型在命名空间中定义:“http://www.example.com/foo”。但是FooApplication.xsd中使用它们的XML位置绑定到不同的命名空间 - 默认命名空间(即没有命名空间)。声明:

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

referes实际上不属于这种类型:

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

而是类型:

{no namespace}:FooClient

要使类型引用正确,您需要在&lt; xsd:schema&gt;中添加一个名称空间绑定。在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模式更好。

<强> P.S。 此网站还有一个问题,与此主题非常相关:

How to convert xsd to human readable documentation?

我也提供了answer(虽然有些人认为这是一个有争议的,特别是从主流的角度来看)。不幸的是,到那时我没有这个帐户,所以我无法直接与它联系。