Чередовать несколько значений из двух элементов в контексте родительского элемента?

#xml #csv #xquery

Вопрос:

У меня есть такие данные:

 <?xml version="1.0" encoding="UTF-8"?>
<colors>
   <color id="ff0000">
      <label language="en">red</label>
      <label language="de">rot</label>
      <label language="es">rojo</label>
   </color>
   <color id="008000">
      <label language="en">green</label>
      <label language="de">gruen</label>
      <label language="es">verde</label>
   </color>
   <color id="0000ff">
      <label language="en">blue</label>
      <label language="de">blau</label>
      <label language="es">azul</label>
   </color>
</colors>
 

Я хотел бы преобразовать его в таблицу, подобную этой

  -------- ---------------------------- 
| id     | labels                     |
 -------- ---------------------------- 
| ff0000 | en:red|de:rot|es:rojo      |
 -------- ---------------------------- 
| 008000 | en:green|de:gruen|es:verde |
 -------- ---------------------------- 
| 0000ff | en:blue|de:blau|es:azul    |
 -------- ---------------------------- 
 

Я знаю, как объединить несколько значений из контекста одного и того же родительского элемента, но я не знаю, как вставить атрибут и данные для одного элемента, а затем вставить эти комбинации в родительский элемент.

 declare option output:method "csv";
declare option output:csv "header=yes, separator=tab";

for $color in doc(
  'color_words'
)/colors/color

let $id := data($color/@id)
let $language := fn:normalize-space(string-join($color/label/@language,'|'))
let $label := fn:normalize-space(string-join($color/label,'|'))

return

<csv>
  <record>
    <id>
      {$id}
    </id>
    <language>
      {$language}
    </language>
    <label>
      {$label}
    </label>
  </record>
</csv>
 
  -------- ---------- ------------------- 
| id     | language | label             |
 -------- ---------- ------------------- 
| ff0000 | en|de|es | red|rot|rojo      |
 -------- ---------- ------------------- 
| 008000 | en|de|es | green|gruen|verde |
 -------- ---------- ------------------- 
| 0000ff | en|de|es | blue|blau|azul    |
 -------- ---------- ------------------- 
 

Ответ №1:

Вы можете использовать это выражение let:

 let $label := fn:normalize-space(string-join($color/label/concat(@language,':',.),'|'))
 

Это создаст желаемый результат. Другое выражение let не требуется.