0

Hi, is there any way to add conditions on a tag value?

For example, my xml looks like this:

<Root>
 <Scheduler>
  <DateTimeType>DAY</DateTimeType>
  <DayOfWeek>Sunday</DayOfWeek> --> TAG IS ALLOWED
 </Scheduler>

 <Scheduler>
  <DateTimeType>MONTH</DateTimeType>
  <DayOfWeek>Sunday</DayOfWeek> --> TAG IS NOT ALLOWED
  <DayOfMonth>28</DayOfMonth> --> TAG IS ALLOWED
 </Scheduler>

 <Scheduler>
  <DateTimeType>WEEKDAY</DateTimeType>
  <DayOfWeek>Sunday</DayOfWeek> --> TAG IS ALLOWED
  <TimeOfDay>15:26</TimeOfDay> --> TAG IS ALLOWED
  <DayOfMonth>28</DayOfMonth> --> TAG IS NOT ALLOWED
 </Scheduler>

 <Scheduler>
  <DateTimeType>TIME</DateTimeType>
  <DayOfWeek>Sunday</DayOfWeek> --> TAG IS NOT ALLOWED
  <DayOfMonth>28</DayOfMonth> --> TAG IS NOT ALLOWED
  <TimeOfDay>15:26</TimeOfDay> --> TAG IS ALLOWED
 </Scheduler>
</Root>

I need a XSD Schem that allow/not allows these conditions in my xml

Thanks

shay
  • 2,021
  • 1
  • 15
  • 17
  • possible duplicate of [Conditional on value in xsd](http://stackoverflow.com/questions/25658953/conditional-on-value-in-xsd) – kjhughes Sep 04 '14 at 11:48
  • when trying to use xs:assertion I am getting a message: The 'http://www.w3.org/2001/XMLSchema:assertion' element is not supported in this context. – shay Sep 08 '14 at 06:03

2 Answers2

0

Why not use elements named DAY, MONTH, WEEKDAY, and TIME, instead of pushing the information down into the character content of the element? That is, if for your purposes there are four distinct types of date-time data, why are you calling them all by the same name?

[Addendum] The OP asks for an example. OK, here is an example:

<Root>
  <Scheduler>
    <Day>
      <DayOfWeek>Sunday</DayOfWeek> 
    </Day>
  </Scheduler>

  <Scheduler>
    <DayOfMonth>
      <DayOfWeek>Sunday</DayOfWeek> 
      <DayOfMonth>28</DayOfMonth> 
    </DayOfMonth>
  </Scheduler>

  <Scheduler>
    <Weekday>
      <DayOfWeek>Sunday</DayOfWeek> 
      <TimeOfDay>15:26</TimeOfDay>
      <!--* <DayOfMonth>28</DayOfMonth> not allowed --> 
    </Weekday>
  </Scheduler>

  <Scheduler>
    <Time>
      <!--* Not allowed:
          * <DayOfWeek>Sunday</DayOfWeek> 
          * <DayOfMonth>28</DayOfMonth> 
          *--> 
      <TimeOfDay>15:26</TimeOfDay>
    </Time>
  </Scheduler>
</Root>

Another option, closer in structure to what the OP shows, would be:

<Root>
  <Scheduler>
    <Day/>
    <DayOfWeek>Sunday</DayOfWeek> 
  </Scheduler>

  <Scheduler>
    <DayOfMonth/>
    <DayOfWeek>Sunday</DayOfWeek> 
    <DayOfMonth>28</DayOfMonth> 
  </Scheduler>

  <Scheduler>
    <Weekday/>
    <DayOfWeek>Sunday</DayOfWeek> 
    <TimeOfDay>15:26</TimeOfDay>
    <!--* <DayOfMonth>28</DayOfMonth> not allowed --> 
  </Scheduler>

  <Scheduler>
    <Time/>
    <!--* Not allowed:
        * <DayOfWeek>Sunday</DayOfWeek> 
        * <DayOfMonth>28</DayOfMonth> 
        *--> 
    <TimeOfDay>15:26</TimeOfDay>
  </Scheduler>
</Root>

With either design, the appropriate constraints are trivial to define.

C. M. Sperberg-McQueen
  • 24,596
  • 5
  • 38
  • 65
0

Here is an answer that uses the tags used by the OP. It works only with XSD 1.1 due to the assert tests.

  <xs:element name="Scheduler">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" name="DateTimeType" type="DateTimeType"/>
        <xs:element minOccurs="0" maxOccurs="1" name="DayOfWeek" type="xs:string"/>
        <xs:element minOccurs="0" maxOccurs="1" name="DayOfMonth" type="xs:string"/>
        <xs:element minOccurs="0" maxOccurs="1" name="TimeOfDay" type="xs:string"/>
      </xs:sequence>
      <xs:assert test="if (./DateTimeType = 'DAY' and (./DayOfMonth or ./TimeOfDay)) then false() else true() "/>
      <xs:assert test="if (./DateTimeType = 'MONTH' and ./DayOfWeek ) then false() else true()"/>
      <xs:assert test="if (./DateTimeType = 'WEEKDAY' and ./DayOfMonth) then false() else true()"/>
      <xs:assert test="if (./DateTimeType = 'TIME' and (./DayOfWeek or ./DayOfMonth)) then false() else true()"/>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="DateTimeType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="DAY"/>
      <xs:enumeration value="MONTH"/>
      <xs:enumeration value="WEEKDAY"/>
      <xs:enumeration value="TIME"/>
    </xs:restriction>
  </xs:simpleType>

While the enumeration of the DateTimeType wasn't part of the question, I would use it to limit the values. Without it values such as day or even dAY wouldn't be checked. If they should be allowed the assert statements would have to be expanded.

It would be possible to write one long, very complex assert statement instead of 4, but with individual statements the error message is more helpful as it is easier which part of the test failed.