Defining assertions depending on both attributes and elements in xsd 1.1

馋奶兔 提交于 2020-01-07 02:25:29

问题


I need to define the following situation in my XSD Schema. This is an example of my XML:

<initialization>

  <stat name="SelfActualization" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>
  <stat name="Social" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>

  <staticAction name="Study" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

  <staticAction name="Greetings" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

  <staticAction name="Eat" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />
  </staticAction>

</initialization>

1st assertation that I need: I can define as many "stat" elements as I want (in this case only 2) and I already managed to obtain this behavior. What I don't know how to do is: in any of my "StaticActions" I need that all the "stats" previously defined above are named again (as elements, this is something I already do through the xs:anyType element but I need an assertation which controls that the names correspond), AND in the same order they have been defined at the beginning. As we can see in the example indeed both "SelfActualization" and "Social" are there and in the right order in all my StaticActions. If another "stat" not defined before, or if one of the "stats" defined is missing, or if the order is wrong, the XML has to be refused. My XSD looks like this so far:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="initialization" type="initializationType" />

<xs:complexType name="initializationType">
  <xs:sequence>
    <xs:element  minOccurs="0" maxOccurs="unbounded" ref="stat"/>
    <xs:element  minOccurs="0" maxOccurs="unbounded" ref="staticAction"/>
  </xs:sequence>
</xs:complexType>

<xs:element name="staticAction" type="StaticActionType"/>

<xs:complexType name="StaticActionType">
    <xs:complexContent>
        <!-- Base is anyType -->
        <xs:extension base="xs:anyType">
            <xs:attribute name="name" type="xs:string"/>
            <!-- Check that every "dynamic" child has the two integer attributes and no other attributes -->
            <xs:assert test="every $element in ./* satisfies 
                ($element[
                    matches(@reqPoints, '^[+-]?\d+$') and
                    matches(@gainedPoints, '^[+-]?\d+$') and
                    count(@*=2)])"/>
            <!-- Test that there is no content in staticAction nor in the "dynamic" nodes -->
            <xs:assert test="matches(string(.), '^\s*$')"/>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

2nd assertation that I need: I declare the StaticActions at the beginning of my xsd schema by using a simple xs:sequence because I need exactly a certain number of those and in a certain order. There, I want to make sure that these staticActions have proper names (through the "name" attribute specified in the staticAction definition): for example I want "Study" "Greetings" and "Eat" . So I need to check that in my XML all the 3 of them "Study", "Greetings" and "Eat" are there, through a simple assertion.

EDIT: Last point is: My staticAction needs to contain 2 static elements as well besides the dynamic ones like shown in the following example:

<initialization>

  <stat name="SelfActualization" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>
  <stat name="Social" range="" init="" tickValue="" colorR="" colorG="" colorB=""/>

  <staticAction name="Study" >
    <SelfActualization reqPoints="0" gainedPoints="0" />
    <Social reqPoints="0" gainedPoints="0" />

    <RequiredAction action="string" cardinality="int" />
    <SuccessLikelihood likelihood="int" />
  </staticAction>

Therefore I need to modify my definition of the "StaticAction" and modify some of the assertions that checks all of the childs of staticAction.


回答1:


For the first requeriment you can use the following assertion inside initializationType:

<xs:assert test="every $staticAction in ./staticAction satisfies deep-equal(data($staticAction/*/name()), data(./stat/@name)) "/>

This ensures that every staticAction contains childs with node names equal to the attribute name of the stat elements in the same order.

For the second requirement you can use this simple assertion supposing that order is not important and that values can be repeated:

<xs:assert test="every $staticAction in ./staticAction satisfies $staticAction/@name = ('Study', 'Greetings', 'Eat') "/>

This can also be modelated in XSD:

<xs:attribute name="name">
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="Study"/>
            <xs:enumeration value="Greetings"/>
            <xs:enumeration value="Eat"/>
        </xs:restriction>
    </xs:simpleType>
</xs:attribute>

Otherwise, if values cannot be repeated but must appear you can use three diferent assertions to ensure that every value exsists one time (e.g: count(./staticAction[@name='Eat']) = 1).



来源:https://stackoverflow.com/questions/30896717/defining-assertions-depending-on-both-attributes-and-elements-in-xsd-1-1

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!