XQuery: извлечь все вложенные xs: attributeGroup

#xquery #basex

#xquery #basex

Вопрос:

 <xs:attributeGroup name="personattr">
  <xs:attribute name="attr1" type="xs:string"/>
  <xs:attribute name="attr2" type="xs:integer"/>
  <xs:attributeGroup ref="personattr2">
</xs:attributeGroup>

<xs:attributeGroup name="personattr2">
  <xs:attribute name="attr12" type="xs:string"/>
  <xs:attribute name="attr22" type="xs:integer"/>
  <xs:attributeGroup ref="personattr3">
</xs:attributeGroup>

<xs:attributeGroup name="personattr3">
  <xs:attribute name="attr13" type="xs:string"/>
  <xs:attribute name="attr23" type="xs:integer"/>
</xs:attributeGroup>

<xs:attributeGroup name="personattr4">
  <xs:attribute name="attr14" type="xs:string"/>
  <xs:attribute name="attr24" type="xs:integer"/>
</xs:attributeGroup>
  

Учитывая приведенный выше пример файла XSD, как мне извлечь все вложенные attributeGroup, начиная с определенной attributeGroup? personattr Оттуда есть personattr2 внутри. Внутри personattr2 есть personattr3 . Результат не должен содержать personattr4 .

Ответ №1:

Вы можете сделать это легко, перейдя к ссылочным дочерним группам с помощью рекурсивной пользовательской функции:

 declare function local:groups-below($groups, $name) {
  $name,
  for $ref in $groups[@name = $name]/xs:attributeGroup/@ref/string()
  return local:groups-below($groups, $ref)
};

local:groups-below($all-groups, 'personattr')
  

Это возвращает следующие имена групп:

 personattr
personattr2
personattr3
  

Если вместо этого вам нужны целые элементы, просто верните их вместо их имен:

 declare function local:groups-below($groups, $name) {
  let $group := $groups[@name = $name]
  return (
    $group,
    for $ref in $group/xs:attributeGroup/@ref/string()
    return local:groups-below($groups, $ref)
  )
};

local:groups-below($all-groups, 'personattr')
  

Это возвращает следующую последовательность:

 <xs:attributeGroup xmlns:xs="http://www.w3.org/2001/XMLSchema" name="personattr">
  <xs:attribute name="attr1" type="xs:string"/>
  <xs:attribute name="attr2" type="xs:integer"/>
  <xs:attributeGroup ref="personattr2"/>
</xs:attributeGroup>,
<xs:attributeGroup xmlns:xs="http://www.w3.org/2001/XMLSchema" name="personattr2">
  <xs:attribute name="attr12" type="xs:string"/>
  <xs:attribute name="attr22" type="xs:integer"/>
  <xs:attributeGroup ref="personattr3"/>
</xs:attributeGroup>,
<xs:attributeGroup xmlns:xs="http://www.w3.org/2001/XMLSchema" name="personattr3">
  <xs:attribute name="attr13" type="xs:string"/>
  <xs:attribute name="attr23" type="xs:integer"/>
</xs:attributeGroup>
  

Комментарии:

1. Разве последняя строка не должна быть local:groups-below(//attributeGroup, 'personattr') ?

2. Входные данные, указанные в вопросе, не являются допустимым XML-узлом, поэтому я предположил, что это последовательность, привязанная к некоторой переменной (здесь $all-groups ). Вам также нужны только xs:attributeGroup элементы верхнего уровня, а не те, у @ref которых есть атрибуты. Но если весь документ XSD является элементом контекста, тогда local:groups-below(//xs:attributeGroup, 'personattr') будет возвращен правильный результат.

3. На самом деле я хочу, чтобы все узлы xs: attributeGroup возвращались в виде последовательности. В этом случае, attributeGroup с именем personattr, personattr2, personattr3 в последовательности. В любом случае я дам вам кредиты

4. Я расширил свой ответ, чтобы также показать, как вернуть сами xs:attributeGroup элементы.

5. Я не понимаю ваш код. Функция local:groups-ниже возвращает последовательность. Разве конечный результат не является вложенной последовательностью, например (personattr, (personattr2, (personattr3)))?