【发布时间】:2020-11-16 17:43:47
【问题描述】:
XSD 是否可以允许一组有限的子节点名称,但允许每个子节点名称的 0-无限实例,以任何顺序?
据我所知,ns:any 允许任何订单,但每个订单不超过一个实例,ns:sequence 需要指定的订单,而ns:choice 将您限制为列表中的一个。
但我似乎也不能只拥有没有订单指示符的 ns:simpleType 或 ns: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:group、ns:union 和ns: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 个不同的任务选项,其中任何一个都可以嵌套在任务的 <preprocess> 节点中。它们也可以出现在<package> 中,但一个包也可以包含另一个嵌套的<package>,它本身包含任务和包。任务和包的顺序都是可变的。
目标是不需要维护重复的任务列表来处理包节点中的内容与任务预处理节点中的内容之间的差异。
【问题讨论】:
标签: powershell xsd