Есть ли способ иметь несколько, если без других? - PullRequest
0 голосов
/ 04 июня 2019

Мне нужно проверить 3 атрибута узла. Проблема в том, что я должен возвращать ошибку для каждого атрибута в ошибке, и я не вижу, как это легко сделать.

xquery не очень гибкий, так что ... не так много, чтобы попробовать ...

for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
    return
        if ($theHoldingListsField/@AFL != "MANDATORY") then
        (
            <error id="DPR-CKSEM-DEP-SMF142-2">
                <args>
                    <arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
                    <arg value="AFL = {$theHoldingListsField/@AFL}"/>
                </args>
                <location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
            </error>
        )
        else if ($theHoldingListsField/@attitudeIndicator != "MANDATORY") then
        (
            <error id="DPR-CKSEM-DEP-SMF142-2">
                <args>
                    <arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
                    <arg value="attitudeIndicator = {$theHoldingListsField/@attitudeIndicator}"/>
                </args>
                <location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
            </error>
        )

Так что в этом примере я хочу, чтобы была возможность вызвать 3 ошибки одновременно, а не одну из них (как сейчас). Я даже не знаю, возможно ли это ...

Спасибо!

Ответы [ 3 ]

4 голосов
/ 04 июня 2019

Начните с ввода повторного кода в функцию:

declare function local:check($att as attribute()) as element(error)? {
  if ($att != "MANDATORY") then (
    <error id="DPR-CKSEM-DEP-SMF142-2">
      <args>
        <arg value="{$att/../ancestor::node()/@id}"/>
        <arg value="{name($att)} = {$att}"/>
      </args>
      <location value="{functx:path-to-node-with-pos($att/..)}"/>
    </error>
  ) else ()
};

Тогда ваша логика уменьшится до

for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
    return (local:check($theHoldingListsField/@AFL),
            local:check($theHoldingListsField/@attitudeIndicator),
            ...)
2 голосов
/ 04 июня 2019

Другим вариантом является более функциональный подход к программированию.

Мы можем обобщить ваш тест в функцию, которая работает с theHoldingListsField, поскольку она имеет только два инварианта: имя атрибута ($attr-name) и код ошибки ($error-id).

Мы в основном зацикливаем атрибуты (с кодами ошибок), которые вы хотите проверить, и вызываем функцию local:test для каждого, например,

declare function local:test($theHoldingListsField, $attr-name, $error-id) {
    $theHoldingListsField/@*[local-name() eq $attr-name][. ne "MANDATORY"] !
       <error id="{$error-id}">
         <args>
          <arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
          <arg value="{$attr-name} = {.}"/>
         </args>
         <location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
       </error>
};


let $tests := (
  ["AFL", "DPR-CKSEM-DEP-SMF142-2"],
  ["attitudeIndicator", "DPR-CKSEM-DEP-SMF142-2"]
)

for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
let $test-fn := local:test($theHoldingListsField, ?, ?)
return
  $tests ! fn:apply($test-fn, .)

В приведенном выше примере используются функции XQuery 3.1, такие как массивы ([]), применение частичных функций (?), оператор простого отображения (!) и функции высшего порядка (fn:apply) , Я бы посоветовал узнать об этом из спецификации XQuery 3.1 W3C.

Это также можно переписать, чтобы удалить for, и вместо этого включить функцию local:test для всех полей (т. Е. theHoldingListsFields).

2 голосов
/ 04 июня 2019

В стандартном XQuery нет if без else, поскольку if / then / else является выражением , которое в каждом случае должно вычисляться до некоторого возвращаемого значения ( см. функциональное программирование ).

Если вы хотите вернуть пустую последовательность, когда условие ошибки не выполнено, вы можете сделать это явно, отдельно для каждой ошибки. Затем вы можете собрать все последовательности с нулем или одним элементом в одну, которая автоматически сглаживается:

for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
return (
  if ($theHoldingListsField/@AFL != "MANDATORY") then (
    <error id="DPR-CKSEM-DEP-SMF142-2">
      <args>
        <arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
        <arg value="AFL = {$theHoldingListsField/@AFL}"/>
      </args>
      <location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
    </error>
  ) else (),
  if ($theHoldingListsField/@attitudeIndicator != "MANDATORY") then (
    <error id="DPR-CKSEM-DEP-SMF142-2">
      <args>
        <arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
        <arg value="attitudeIndicator = {$theHoldingListsField/@attitudeIndicator}"/>
      </args>
      <location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
    </error>
  ) else ()
)
...