【问题标题】:XSD 1.1 Check if an attribute exists in another elementXSD 1.1 检查属性是否存在于另一个元素中
【发布时间】:2016-02-24 13:04:56
【问题描述】:

我的 XML 文件序列和状态关系中有 2 个主要部分。序列部分定义为。根据下面定义的 4 个属性,Transition 元素应该是唯一的。

<xs:element name="Transition">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Element1" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="Element2" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="Element3" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="stateName" type="xs:string" use="required"/>
        <xs:attribute name="A" type="xs:string" use="required"/>
        <xs:attribute name="B" type="xs:string" use="required"/>
        <xs:attribute name="C" type="xs:string" use="optional"/>
    </xs:complexType>
</xs:element>
<xs:element name="Sequence">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Transition" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="optional"/>
        <xs:attribute ref="xml:base"/>
    </xs:complexType>
    <xs:unique name="uniqueTransition">
        <xs:selector xpath=".//Transition"/>
        <xs:field xpath="@stateName"/>
        <xs:field xpath="@A"/>
        <xs:field xpath="@B"/>
        <xs:field xpath="@C"/>
    </xs:unique>
</xs:element>

和 StateRelations 部分定义如下。 “stateName1”实际上是与Transition的“stateName”(key)相关的外键(keyref)。 注意:关系元素实际上是递归的。

<xs:element name="Relation">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="stateName1" type="xs:string" use="required"/>
    </xs:complexType>
</xs:element>
<xs:element name="StateRelations">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="optional"/>
        <xs:attribute ref="xml:base"/>
    </xs:complexType>
</xs:element>

问题出现在以下场景中。由于 Transition 具有基于 4 个属性的唯一约束,因此以下 XML 是有效的。

<Transition stateName="S3" A="a1" B="b1" C="c"/>
<Transition stateName="S3" A="a" B="b" C="c"/>

如您所见,stateName=S3 可以重复多次。但是这种重复打破了Transition和Relationship之间的主外键关系。原因:stateName 可以在 Transitions 中重复。现在,我们在这里发生了冲突。我的最终目标是拥有

  1. 基于 4 个属性的唯一序列

  2. StateRelations 中的每个 stateName1 都应该是有效的 stateName 在转换中定义。

到目前为止,我知道 key-keyref 在我的场景中不起作用,所以我开始研究 assert 但我无法让它起作用。我尝试了以下方法,但似乎没有任何效果。

    <xs:element name="Relation">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="stateName1" type="xs:string" use="required"/>

        <xs:assert test="matches( .//Transition/@stateName , @stateName1 )"/>
        <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, @stateName1)]" />
        <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, string( @stateName1 ))]/@stateName = string(@stateName1) "/>

    </xs:complexType>
</xs:element>

编辑:这是 XSD(我省略了一些细节)。 现在,我想以某种方式验证/Replay/StateRelations/Relation/@stateName1 是否存在于/Replay/Sequence/Transition/@stateName 中。我不能使用 key/keyref 因为/Replay/Sequence/Transition/@stateName 不会是唯一的。

<Replay>
   <xs:element name="Relation">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="stateName1" type="xs:string" use="required"/>
        <xs:assert test="matches( .//Transition/@stateName , @stateName1 )"/>
        <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, @stateName1)]" />
        <xs:assert test="/Replay/Sequence/Transition[contains(@stateName, string( @stateName1 ))]/@stateName = string(@stateName1) "/>
    </xs:complexType>
</xs:element>
<xs:element name="StateRelations">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="optional"/>
        <xs:attribute ref="xml:base"/>
    </xs:complexType>
</xs:element>

<xs:element name="Transition">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Element1" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="Element2" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="Element3" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="stateName" type="xs:string" use="required"/>
        <xs:attribute name="A" type="xs:string" use="required"/>
        <xs:attribute name="B" type="xs:string" use="required"/>
        <xs:attribute name="C" type="xs:string" use="optional"/>
    </xs:complexType>
</xs:element>
<xs:element name="Sequence">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="Transition" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="optional"/>
        <xs:attribute ref="xml:base"/>
    </xs:complexType>
    <xs:unique name="uniqueTransition">
        <xs:selector xpath=".//Transition"/>
        <xs:field xpath="@stateName"/>
        <xs:field xpath="@A"/>
        <xs:field xpath="@B"/>
        <xs:field xpath="@C"/>
    </xs:unique>
</xs:element>
</Replay>

【问题讨论】:

    标签: xml xpath xsd xsd-validation xsd-1.1


    【解决方案1】:

    我无法确定您文档的顶级结构。从您的非工作断言中的路径猜测,我猜您的顶级元素是 Replay,它有一个分支 /Replay/Sequence/Transition 可能还有另一个单独的分支 /Replay/StateRelations/Relation?

    如果是这种情况,那么定义Transition 和Relation 之间关系的约束需要在共同祖先级别定义,即Replay。您可以在此级别使用 key/keyref 或使用断言来定义它,但无论哪种方式影响两个不同元素的约束总是需要在共同祖先级别定义:因为根植于该祖先的树是最小的自我- 包含无效的文档部分。

    更具体地说,请注意断言不能查看以定义断言的元素为根的子树之外的数据。这是关于该元素及其内容的断言,而不是关于该元素周围上下文的断言。

    【讨论】:

    • 是的,我的顶级元素是重播。你是完全正确的。谢谢。有一次,我将断言移至重播级别,它运行良好。唯一的问题是我不能使用 key/keyref 因为转换中的 stateName 不是唯一的。所以,既然断言是我唯一的选择,我必须在 Relation 标签之外定义它,我是否在 XPath 中使用了某种 for 循环来检查在 Relation 中定义的 stateNames 是否存在于 Transition 中?
    • 抱歉,我认为我不太了解您的结构,无法理解为什么使用 key/keyRef 是一个问题。当您谈到 XPath 中的循环时,这是用于 key/keyRef 还是用于断言? XPath 当然没有循环,它完全是声明式的并且适用于节点集。
    • 抱歉不清楚。我已经更新了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多