XSD 使用基于父属性的不同序列元素验证 XML

问题描述

我已经查看了关于 stackoverflow 的其他提及,但实际上看不到任何符合我正在寻找的内容

我已经使用 JAXB 生成一个 .xsd,但不幸的是它不是太好,所以当我意识到有些东西似乎与我遵循的其他模式的逻辑并不真正匹配时,我手动创建了一个

与其进行冗长的描述,不如将其显示代码我有很多 xml 文档,有重复的元素,这些元素根据它们的父 (ItemGroup) 元素 id 有所不同。其中一些 id 是重复的(如图所示),一些只会出现一次(它们以 0 结尾或者是 DocDetails 的一部分)。此外,特定“id”的元素始终是相同的元素列表。

在示例中,以 0 结尾的元素只出现一次,以 1 结尾的元素是重复元素(尽管通常不会超过 2 个),以 2 结尾的元素重复任意次数。这个后缀编号是人为的,以使其显而易见,但相同的固定 ItemGroup id 有 1 个或重复的元素。

<?xml version="1.0" encoding="UTF-8"?>
<DocTree xmlns="http://wolfedgx.com/doc-list/1.0/">
    <DocDetails>
        <Title>Book Title</Title>
        <Author>Author Name</Author>
    </DocDetails>
    <ItemGroup id="10">
        <GroupCategory>52</GroupCategory>
        <Genre>Horror</Horror>
    </ItemGroup>
    <ItemGroup id="11">
        <GroupHierarchy>52</GroupHierarchy>
        <Delivery>2</Delivery>
        <GroupMember>95</GroupMember>
    </ItemGroup>
    <ItemGroup id="11">
        <GroupHierarchy>51</GroupHierarchy>
        <Delivery>55</Delivery>
        <GroupMember>100</GroupMember>
    </ItemGroup>
    <ItemGroup id="22">
        <GroupMemberNo>95</GroupMemberNo>
        <StoreName>Denver</StoreName>
        <StoreID>92</StoreID>
        <Staff>32</Staff>
    </ItemGroup>
    <ItemGroup id="52">
        <StoreREF>92</StoreREF>
        <StorePrice>1.99</StorePrice>
        <StoreLogistics>2.00</StoreLogisics>
        <ItemStored>5A</ItemStored>
        <LazyRef>Yes</LazyRef>
    </ItemGroup>
    <ItemGroup id="22">
         <GroupMemberNo>95</GroupMemberNo>
        <StoreName>Alaska</StoreName>
        <StoreID>22</StoreID>
        <Staff>2</Staff>
    </ItemGroup>
    <ItemGroup id="52">
        <StoreREF>22</StoreREF>
        <StorePrice>2.99</StorePrice>
        <StoreLogistics>4.00</StoreLogisics>
        <ItemStored>1A</ItemStored>
        <LazyRef>Mixed</LazyRef>
    </ItemGroup>
    <ItemGroup id="22">
         <GroupMember>100</GroupMember>
        <StoreName>Washington</StoreName>
        <StoreID>34</StoreID>
        <Staff>2</Staff>
    </ItemGroup>
    <ItemGroup id="52">
        <StoreREF>34</StoreREF>
        <StorePrice>2.99</StorePrice>
        <StoreLogistics>4.00</StoreLogisics>
        <ItemStored>1A</ItemStored>
        <LazyRef>Mixed</LazyRef>
    </ItemGroup>
    <ItemGroup id="90">
        <Misc>No additional information</Misc>
    </ItemGroup>
 </DocTree>

我想知道是否可以根据它们的 ItemGroup id 号来验证这些元素。我不能使用 xsd 1.1,因为我必须使用 JAXB 来处理数据。另外,XML 是固定的,所以我无法重构它。您会注意到数据实际上是相互链接的,验证它会很好,但这不是绝对必要的,目前仅验证基于 ItemGroups 的元素会很好。

下面是对这个问题的补充,但没有回答。这是一个建议的 xsd 解决方法,但避免了基于 InfoGroup id 的验证,并且应该允许每个属性多次/0 次出现。

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://wolfedgx.com/doc-list/1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="DocTree" type="ns:DocTree" xmlns:ns="http://wolfedgx.com/doc-list/1.0/"/>
<xs:complexType name="DocDetails">
    <xs:sequence>
        <xs:element type="xs:string" name="Title" maxOccurs="unbounded" minOccurs="0" />
        <xs:element type="xs:string" name="Author" maxOccurs="unbounded" minOccurs="0" />
   </xs:sequence>
  </xs:complexType>
    <xs:complexType>
        <xs:element name="InfoGroup">
            <xs:sequence>
                <xs:element type="xs:int" name="GroupCategory" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:string" name="Genre" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="GroupHierarchy" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="Delivery" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="GroupMember" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="GroupMemberNo" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:string" name="StoreName" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="StoreID" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="Staff" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:int" name="StoreREF" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:float" name="StorePrice" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:float" name="StoreLogistics" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:string" name="ItemStored" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:string" name="LazyRef" maxOccurs="unbounded" minOccurs="0" />
                <xs:element type="xs:string" name="Misc" maxOccurs="unbounded" minOccurs="0" />
            </xs:sequence>
            <xs:attribute type="xs:int" name="id"/>
        </xs:element>
    </xs:complexType>
</xs:schema>

解决方法

共现约束的经典示例。这需要 XSD 1.1。

JAXB 实际上只适用于具有高度规则和稳定结构的 XML。在使用 JAXB 处理 XML 之前,请考虑使用 XSLT 将其转换为其他内容。