在渲染多个TEI元素时避免基数问题

时间:2017-10-29 16:46:35

标签: xml xslt xquery exist-db tei

我试图在此TEI标头中呈现$ respStmt条目:

<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中的元素拼写出来。很多,非常感谢Martin Honnen和milijan!

以下是整个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中的每个$ name都被复制 - 冒号左侧的信息是正确的,但是在冒号的右侧,所有的$名字都被复制了。精氨酸!

2 个答案:

答案 0 :(得分:0)

我不完全确定您正在寻找的输出是什么,但这就是我理解它的方式。 假设您有一个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>

解决方案是Martin Honnen对你的问题的评论。

如果您希望输出如下:

<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是$ header。试试这个:

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>
}

答案 1 :(得分:0)

成功!经过大量的反复试验,这就是我想出来的:

{ 
 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,以逗号分隔。我觉得非常完成了。谢谢,大家,谢谢你的帮助!