xsd - Утверждение условия проверки всех потомков

У меня есть следующий XML:

<request>
  <resource>
    <regime>payed</regime>
  </resource>
  <user>
    <contract>
      <data>
        <discount>true</discount>
        <priceInPercents>0</priceInPercents>
      </data>
      <data>
        <discount>false</discount>
        <priceInPercents>20</priceInPercents>
      </data>
      <data>
        <discount>false</discount>
        <priceInPercents>0</priceInPercents>
      </data>
   </contract>
  </user>
</request>

XML следует файлу XSD, в который я хотел бы добавить условие, которое проверяет следующее: если режим "оплачен", то любой priceInPercents не может быть равен "0", если только элемент скидки в этом конкретном элементе данных не равен " правда'. (Возможные значения для режима только "оплачено" или "бесплатно"). Я пытаюсь сделать это, используя assert на уровне запроса следующим образом:

<assert test="./resource/regime/text() = 'free' 
              or ./user/contract
                 /data[discount=false]
                 /priceInPercents != 0 
              or ./user/contract
                 /data[priceInPercents = 0]
                 /discount = true "/>

В этом случае валидатор говорит, что все в порядке, потому что вторая часть условия выполняется во втором случае, а третья часть выполняется в первом случае. Третий случай не соответствует ни одному из условий, но это не имеет значения, потому что assert уже нашел совпадение. Мне нужно переписать XPath, чтобы проверить шаблон для всех элементов данных, но я действительно не знаю, как это сделать.

1 ответ

Если я вас правильно понял, то условие, которое вы хотите применить, заключается в том, что в данном запросе либо

  • resource/regime eq 'free', или же
  • для каждого user/contract/data элемент, либо
    • priceInPercents ненулевой, или
    • discount eq 'true'

Один из способов справиться с этим - обратить булеву полярность второго основного дизъюнкта и сказать: "нет data элемент с обоими priceInPercents eq '0' and discount eq 'false', Вы могли бы сказать, что так:

<assert test="./resource/regime eq 'free' 
              or not(./user/contract
                 /data[discount eq 'false' and priceInPercents eq 0])"/>

Это может быть немного проще, если вы используете универсально выраженное выражение; они принимают форму every ... satisfies ..., В этом случае одной из возможных формулировок будет:

<assert test="./resource/regime = 'free' 
              or every $d in ./user/contract/data
                 satisfies
                 ($d/discount eq 'true' 
                 or $d/priceInPercents ne 0)"/>
Другие вопросы по тегам