【问题标题】:XSD 0-unlimited nodes in any orderXSD 0-任意顺序的无限节点
【发布时间】:2020-11-16 17:43:47
【问题描述】:

XSD 是否可以允许一组有限的子节点名称,但允许每个子节点名称的 0-无限实例,以任何顺序?

据我所知,ns:any 允许任何订单,但每个订单不超过一个实例,ns:sequence 需要指定的订单,而ns:choice 将您限制为列表中的一个。

但我似乎也不能只拥有没有订单指示符的 ns:simpleTypens:complexType

或者,我可以在不验证 XSD 的情况下导入我的 XML,然后根据它们自己的 XSD 验证每个所需的节点,但我似乎找不到直接验证 [Xml.Element] 的方法。也许我可以获取每个节点并从中创建一个临时的[Xml.Document] 进行验证,但据我所知,针对 XSD 验证 XML 的唯一方法是从文件中读取,并写入数百个临时文件仅仅为了验证一个节点而进行数千次似乎非常低效。

我花了很多时间来开发我的 XSD,所以我希望有一个基于 XSD 的解决方案。但至少所有这些工作都产生了比我原本拥有的更加一致的 XML,并且 XSD 练习为我需要验证 XML 的代码提供了一种规范。那里有一些安慰。

编辑:我发现的潜在解决方案是创建一个ns:group,其中包含一个ns:choice,其中包含所有子节点为minOccurs='0' maxOccurs='1',然后使用<xs:group ref="TaskGroup" minOccurs='0' maxOccurs='unbounded'/> 引用需要这些节点的那个组。仍然不理想,因为另一个微妙之处是在两个地方我只需要任务(其中可能有 30 个),在另一个位置我还需要允许一个名为 <package> 的节点可以与其他任务节点穿插。在这一点上,我有两组,其中绝大多数是相同的 30 个任务,唯一的区别是一个也有一个<package>。而且似乎没有办法同时使用ns:groupns:unionns:choice 来获得所需的结果。该死的微软!

很丑,我可能仍然会放弃 XSD 并编写自己的验证代码。

编辑:我确实尝试过使用像这样的ns:extension,但我得到一个错误The 'http://www.w3.org/2001/XMLSchema:extension' element is not supported in this context.

    <xs:complexType name='TaskList'>
        <xs:choice>
            <xs:element name='taskCopy' type='Task_Copy' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskCreateFolder' type='Task_CreateFolder' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskDelete' type='Task_Delete' minOccurs='0' maxOccurs='1'/>
            
            <xs:element name='taskExecuteProgram' type='Task_ExecuteProgram' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskInstallProgram' type='Task_InstallProgram' minOccurs='0' maxOccurs='1'/>
            
            <xs:element name='taskInventoryHardware' type='Task_InventoryHardware' minOccurs='0' maxOccurs='unbounded'/>
            <xs:element name='taskInventorySoftware' type='Task_InventorySoftware' minOccurs='0' maxOccurs='unbounded'/>
            
            <xs:element name='taskManageAsset' type='Task_ManageAsset' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskManageNetworkLocation' type='Task_ManageNetworkLocation' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskManageManageMappedDrive' type='Task_ManageManageMappedDrive' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskManageZipFile' type='Task_ManageZipFile' minOccurs='0' maxOccurs='1'/>
            
            <xs:element name='taskMirror' type='Task_Mirror' minOccurs='0' maxOccurs='1'/>
            <xs:element name='taskSetRegistryValue' type='Task_SetRegistryValue' minOccurs='0' maxOccurs='1'/>
        </xs:choice>
    </xs:complexType>
    <xs:complexType name='PackageList'>
        <xs:extension base="TaskList">
            <xs:choice>
                <xs:element name='package' type='xs:string' minOccurs='0' maxOccurs='1'/>
            </xs:choice>
        </xs:extension>
    </xs:complexType>

所以,在我看来,至少在 XSD 1.0 中,ns:choice 非常有限,不能合并或扩展。

EDIT2:澄清一下,这是我的 XML 的简化示例。

<packages>
    <package id="ParentPackage">
        <taskCopy id="SimpleTask">
            <process>
                <source>PATH TO... source</source>
                <destination>PATH TO... destination</destination>
            </process>
        </taskCopy>
        <package>NestedPackage</package>
        <taskCopy id="ComplexTask">
            <preprocess>
                <taskDelete>
                    <process>
                        <path>[Product~Journals]\*</path>
                    </process>
                </taskDelete>
            </preprocess>
            <process>
                <source>PATH TO... source</source>
                <destination>PATH TO... destination</destination>
            </process>
        </taskCopy>
    </package>
    <package id="NestedPackage">
        <taskCopy id="AnotherSimpleTask">
            <process>
                <source>PATH TO... source</source>
                <destination>PATH TO... destination</destination>
            </process>
        </taskCopy>
    </package>
</packages>

有 30 个不同的任务选项,其中任何一个都可以嵌套在任务的 &lt;preprocess&gt; 节点中。它们也可以出现在&lt;package&gt; 中,但一个包也可以包含另一个嵌套的&lt;package&gt;,它本身包含任务和包。任务和包的顺序都是可变的。

目标是不需要维护重复的任务列表来处理包节点中的内容与任务预处理节点中的内容之间的差异。

【问题讨论】:

    标签: powershell xsd


    【解决方案1】:

    定义一个包含所有可选子项的选项的复杂类型,并将该复杂类型分配给所有子项的父项。

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
        <xs:element name="Root" type="randomType"/>
        <xs:complexType name="randomType">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="a"/>
                <xs:element name="b"/>
                <xs:element name="c"/>
            </xs:choice>
        </xs:complexType>
    </xs:schema>
    

    这样的 xml 仍然有效

    <?xml version="1.0" encoding="UTF-8"?>
    <Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <b>a</b>
        <a>text</a>
        <b>a</b>
        <b>a</b>
        <b>a</b>
        <b>a</b>
        <b>a</b>
        <a>text</a>
    </Root>
    

    【讨论】:

    • 关键是,我有一个大的ns:choice,我可以调用 a-z,然后我还有另一个 ns:choice,我可以调用 1-3,我有两个位置可以使用 a-z第三个需要 a-z AND 1-3。这是我似乎无法做到的两个ns:choice 的结合。看来我需要维护两份 a-z,一份还定义了 1-3,一份没有。还是我在这里遗漏了什么?
    • 你能添加一个你想用xsd描述的xml的例子吗?从文字中我无法完全理解您想要实现的目标。
    • 我用一些示例 XML 修改了原始帖子。希望这是有道理的。
    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 2021-01-28
    相关资源
    最近更新 更多