Как создать правильный синтаксис для цикла XQuery

#xml #xslt #xquery

#xml #xslt #xquery

Вопрос:

Теперь у меня есть dita composite, например:

 <root>
 <topic>....</topic>
 <topic>....</topic>
 <topic>....</topic>
 <topic>....</topic>
 <topic>....</topic>
</root>
  

И мне просто нужно написать xquery, который в основном создаст ditamap для каждой темы, поэтому повторный ditamap должен выглядеть так:

 <map>
 <topicref>....</topicref>
 <topicref>....</topicref>
 <topicref>....</topicref>
 <topicref>....</topicref>
 <topicref>....</topicref>
</map>
  

Мой текущий Xquery не совсем правильно работает, он способен перехватывать каждую тему, но вместо создания одного ditamp он создает несколько ditamap, по одному для каждой темы:

  $isFoSaved := for $b in $mapNode/*[local-name() = 'topic']
               let                                     
               $topicWithPI := let $holder:=1
               return (
                      <topicref href="1.xml#Begin" navtitle="Begin" scope="local" type="topic"/>
                ),  
  

Могут ли эксперты помочь? Спасибо

Ответ №1:

Я вижу только, что вы встраиваете несколько выражений flwor.

Всякий раз, когда вы используете $x := let $y ... или $x := for $y ... запускаете новое выражение flwor, которое должно быть закрыто return предложением. Следовательно, ваш обрезанный код является недопустимым / неполным: у вас есть два открытых выражения flwor, но только одно return предложение.

Если вы попытаетесь сохранить его плоским, это будет намного проще.

Например:

 <map>{
 let $mapNode := 
   <root>
     <topic>....</topic>
     <topic>....</topic>
     <topic>....</topic>
     <topic>....</topic>
     <topic>....</topic>
    </root>
  for $b in $mapNode/*[local-name() = 'topic']
  return 
    <topicref href="1.xml#Begin" 
              avtitle="Begin"
              scope="local" 
              type="topic"/>
}</map>
  

этот запрос работает на try.zorba-xquery.com , но я не уверен, что это то, что вы ищете?

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

1. Спасибо. Это действительно полезно. Могу ли я спросить вас подробнее, что, если у нас есть вложенные темы (т.Е. Тема внутри темы), можем ли мы зафиксировать это в xquery?

2. Конечно, это то, в чем XQuery / XPath лучше всего. Если вы просто используете $mapNode//*[local-name() = ‘topic’] (двойные шлаши), вы также получите ссылки на темы для всех дочерних элементов. Если вы хотите сохранить иерархию, это немного сложнее: см. Другой ответ.

Ответ №2:

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

 declare function local:topicref($topics)
{
  for $b in $topics
  return 
    <topicref href="1.xml#Begin" 
              avtitle="Begin"
              scope="local" 
              type="topic">{
      local:topicref($b/*[local-name() = 'topic'])
    }</topicref>

};

<map>{
 let $mapNode := 
   <root>
     <topic><topic>....</topic></topic>
     <topic>....</topic>
     <topic>....</topic>
     <topic>....</topic>
     <topic>....</topic>
    </root>
 return 
   local:topicref(
     $mapNode/*[local-name() = 'topic']
   )
}</map>
  

Результат:

 <?xml version="1.0" encoding="UTF-8"?>
<map>
  <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic">
    <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic"/>   
  </topicref>
  <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic"/>
  <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic"/>
  <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic"/>
  <topicref href="1.xml#Begin" avtitle="Begin" scope="local" type="topic"/>
</map>