xquery соответствия - разрешить несуществующие узлы в цикле - PullRequest
1 голос
/ 10 ноября 2019

У меня есть цикл for и я хочу отфильтровать некоторые узлы, что прекрасно работает:

matches($doc/abc/@def, $filterA)
matches($doc/qwert/@xyz, $filterB)

То, что работает, когда $filterA, $filterB или оба пустые, возвращает каждый узел,Однако не работает возврат узла, если узел abc или qwert не существует . Для значения по умолчанию я в настоящее время использую "" (пустая строка), есть ли другое значение по умолчанию или другая функция, которую я могу использовать, чтобы она работала?

1 Ответ

1 голос
/ 10 ноября 2019

Вы можете проверить, существуют ли элементы abc и qwert с функцией fn:exists(). Если вы хотите, чтобы он прошел, если ни один из этих элементов не существует, вы можете использовать fn:not(), чтобы отменить тест для abc и qwert существование:

fn:not(fn:exists($doc/abc) and fn:exists($doc/qwert))

Если вы хотите, чтобы условие было выполнено, если либо $filterA, либо $filterB пусто:

fn:not(fn:exists($filterA) and fn:exists($filterB)) 

Вы можете объединить выражения matches() в предикат, чтобы избежать повторения $doc (не слишком большая экономия,но что-то, о чем следует подумать более широко при написании выражений XPath.

$doc[matches(abc/@def, $filterA) and matches(qwert/@xyz, $filterB)] 

Собираем все вместе:

let $filterA := "a"
let $filterB :="b"
let $doc := <doc><abc def="a"/><qwert xyz="b"/></doc>
return
  if (fn:not(fn:exists($doc/abc) and fn:exists($doc/qwert))
      or fn:not(fn:exists($filterA) and fn:exists($filterB)) 
      or $doc[matches(abc/@def, $filterA) and matches(qwert/@xyz, $filterB)])
  then "pass - copy nodes"
  else "fail"
...