Как избежать проблем с кардинальностью при рендеринге нескольких элементов 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, разделенные запятыми. Я чувствую себя очень опытным. Спасибо всем за помощь!