Как избежать проблем с кардинальностью при рендеринге нескольких элементов TEI

Я пытаюсь отобразить записи $respStmt в этом заголовке TEI:

<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="reeve-prog">
<teiHeader>
    <fileDesc>
        <titleStmt>
            <title type="statusBar">The Progress of Romance</title>
            <author>
                <person xml:id="CR" sex="F" href="http://en.wikipedia.org/wiki/Clara_Reeve">
                    <forename>Clara</forename>
                    <surname>Reeve</surname>
                    <born when="1729">1729</born>
                    <died when="1807-12-03">3 December 1807</died>
                    <occupation>Writer</occupation>
                    <occupation>Novelist</occupation>
                    <trait type="Marital Status">Unmarried</trait>
                    <nationality>English</nationality>
                </person>
            </author>
            <respStmt>
                <resp>Transcription and correction</resp>
                <name>Elizabeth Ricketts</name>
                <name>Tonya Howe</name>
            </respStmt>
            <respStmt>
                <resp>Correction, editorial commentary, and markup</resp>
                <name>Incomplete</name>
            </respStmt>
        </titleStmt>
     </filedesc>
   </teiHeader>
</TEI>

В списке, который выглядит так:

<li class="list-unstyled">Transcription and correction: Elizabeth Ricketts, Tonya Howe</li>
<li class="list-unstyled">Correctionm editorial commentary, and markup: Incomplete</li>

Я добавил этот код в более крупную функцию, и он работает с несколькими элементами $ name, но у меня возникает проблема с количеством элементов $ resp:

for $resp in $header
                return
                <li class="list-unstyled">
                    {concat($titleStmt/tei:respStmt/tei:resp, ': ' , string-join($titleStmt/tei:respStmt/tei:name, ', '))                    }
                </li>

Я прописал элементы в concat как часть моего учебного процесса. Огромное спасибо Мартину Хоннену и Милиджану!

Вот файл XQL в целом - я знаю, что это не красиво: https://gist.github.com/tonyahowe/9ec27e9261116bdb11b0cfc2cecc5ea7

ОБНОВЛЕНИЕ: прогресс! Теперь я получаю странное повторение. С этим кодом:

{
                let $respStmt := $header//tei:respStmt
                for $resps in $respStmt
                return
                <li class="list-unstyled">
                    {concat($resps, ': ' , string-join($names, ', '))                    }
                </li>
            }

Я получаю следующий результат:

Transcription and correctionElizabeth RickettsTonya Howe: Elizabeth Ricketts, Tonya Howe, Incomplete
Correction, editorial commentary, and markupIncomplete: Elizabeth Ricketts, Tonya Howe, Incomplete

Похоже, проблема кардинальности $ resp была решена, но теперь каждое имя $ в каждом $respStmt дублируется - информация на левой стороне двоеточия верна, но на правой стороне двоеточия все $ имена воспроизводятся. Arg!

2 ответа

Я не совсем уверен, какой именно результат вы ищете, но я так понимаю. Допустим, у вас есть XML-документ (contributors.xml):

<document>
<respStmt>
  <resp>Transcription, editorial commentary, and markup</resp>
  <name>students of X Y University</name>
  <name>First Specific Contributor</name>
  <name>Second Specific Contributor</name>
  <name>Third Specific Contributor</name>
</respStmt>
<respStmt>
  <resp>Editorial review</resp>
  <name>Reviewer Name</name>
  <name>Reviewer2 Name</name>
</respStmt>
<respStmt>
  <resp>Graphic design</resp>
  <name>Designer Name</name>
</respStmt>
</document>

Если вы хотите, чтобы ваш вывод был таким:

<li class="list-unstyled">Transcription, editorial commentary, and markup: students of X Y University, First Specific Contributor, Second Specific Contributor, Third Specific Contributor</li>
<li class="list-unstyled">Editorial review: Reviewer Name, Reviewer2 Name</li>
<li class="list-unstyled">Graphic design: Designer Name</li>

Вы можете использовать скрипт xquery следующим образом:

let $document := doc('contributors.xml')/*

for $resp-stmt in $document/respStmt
   return
   <li class="list-unstyled">
   {
       concat($resp-stmt/resp, ': ' , string-join($resp-stmt/name, ', '))

   }
   </li>

Решение в комментарии Мартина Хоннена на ваш вопрос.

Если вы хотите, чтобы ваш вывод был таким:

<li class="list-unstyled">Transcription, editorial commentary, and markup: students of X Y University, First Specific Contributor, Second Specific Contributor, and Third Specific Contributor</li>
<li class="list-unstyled">Editorial review: Reviewer Name and Reviewer2 Name</li>
<li class="list-unstyled">Graphic design: Designer Name</li>

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

let $document := doc('contributors.xml')/*
for $resp-stmt in $document/respStmt
let $name := $resp-stmt/name
let $name-count := count($name)
   return
   <li class="list-unstyled">
   {concat($resp-stmt/resp, ': ')}
   {
        if ($name-count le 2)
        then string-join($name, ' and ')
        else
            concat(
                string-join($name[position() = (1 to last() - 1)] , ', '),
                ', and ',
                $name[last()])
   }
   </li>

Решение в коде, который вы предоставили.

Чтобы сделать эти коды xquery работоспособными, вы должны определить правильные пространства имен и использовать их там, где это необходимо.

ОБНОВЛЕНИЕ: Сценарий в этом автономном примере с contributors.xml в качестве входного файла, который вы предоставили, должен дать вам то, что вы пытаетесь достичь:

declare namespace tei = 'http://www.tei-c.org/ns/1.0';    
let $document := doc('contributors.xml')/*

for $resp-stmt in $document//tei:respStmt
return
<li class="list-unstyled">
    {concat($resp-stmt/tei:resp, ': ' , string-join($resp-stmt/tei:name, ', '))}
</li>

В вашем *.xql файле, я полагаю, есть проблема, потому что вы не определили переменную $ resp, как она должна быть определена. Вы на самом деле говорите, что $ resp - это заголовок $. Попробуй это:

for $resp in $header//tei:respStmt
return
<li class="list-unstyled">
   {concat($header//tei:resp, ': ' , string-join($header//tei:name, ', '))}
</li>

Кроме того, в ваших выражениях XPath вам не нужно проходить все узлы, чтобы получить нужного вам потомка. Вместо этого используйте спецификатор // оси, когда этот путь однозначен, потому что запрос к eXist-db будет намного более эффективным в этом смысле.

ОБНОВЛЕНИЕ 2: В вашем новом обновлении вы используете $names переменная, которая находится вне контекста, и именно поэтому вы получаете эти результаты. Я уже дал вам решение в моем предыдущем обновлении, но это вы можете просто скопировать и вставить в ваш скрипт tei2html.xql, и оно должно работать:

{
for $respStmt in $header//tei:respStmt
return
<li class="list-unstyled">
{concat($respStmt/tei:resp, ': ' , string-join($respStmt/tei:name, ', '))}
</li>
}

Успех! После долгих проб и ошибок вот что я придумал:

{ 
 for $respStmt in $respStmts
 let $resp := $respStmt/tei:resp
 let $name := $respStmt/tei:name
 return
 <li class="list-unstyled">
   {$resp} by {string-join($name, ', ')}
 </li>
}

Он возвращает элемент списка для каждого $respStmt, содержащий $ resp и $names, разделенные запятыми. Я чувствую себя очень опытным. Спасибо всем за помощь!

Другие вопросы по тегам