Рендеринг преобразующих XML-элементов внутри других элементов (XSLT, XQL и eXist-db)

Я пытаюсь отобразить титульную страницу в формате xml, что я делаю через приложение eXist-db. Вот соответствующий xml:

<front>
            <titlePage>
                <titlePart>
                    <lb>THE</lb>
                    <lb>ADVENTURES</lb>
                    <lb>OF</lb>
                    <lb>Roderick Random.</lb>
                    <lb><epigraph xml:lang="la">
                        <cit>
                            <quote xml:lang="la" link="http://www.perseus.tufts.edu/hopper/text?doc=Perseus%3Atext%3A1999.02.0062" title="Satires 2.5.8: 'But birth and virtue, unless [attended] with substance, is viler than seaweed.'">
                                <l>Et genus &amp; virtus, nisi cum re, vilior alga est.</l>
                            </quote>
                            <bibl>
                                <author ref="HOR" link="http://en.wikipedia.org/wiki/Horace" title="Quintus Horatius Flaccus, Roman lyric poet of the 1st century BCE">HOR.</author>
                            </bibl>
                        </cit>
                    </epigraph>
                    </lb>
                    <lb>IN TWO VOLUMES.</lb>
                    <lb>VOL. I.</lb>
                    <lb>THE TENTH EDITION.</lb>
                    <hr/>
                    <lb><name type="place">LONDON:</name></lb>
                    <lb>Printed for W. STRACHAN, J. RIVINGTON, R. BALDWIN, HAWES CLARKE, AND COLLINS, W. JOHNSTON, T. CASLON, B. LAW, J. JOHNSON AND Co, W. AND J. RICHARDSON, T. BECKETT, and P.. DeHONDT,</lb>
                    <lb><date title="1775">MDCCLXXV.</date></lb>
                </titlePart>
            </titlePage>
            <pb n="titlepage" facs="smollett.png"/>
        </front>

Графически на данный момент все, что я хочу, это каждые <lb> в отдельной строке. Я также хочу, чтобы <epigraph> появлялись везде, где они есть, в рамках существующей логики титульного листа, то есть в соответствии с существующими <lb>. Этот снимок экрана должен помочь прояснить ситуацию: снимок экрана с некорректной визуализацией страницы

Вот соответствующие биты .xql с преобразованиями xsl. Если вы хотите увидеть все .xql, вы можете увидеть это здесь (опять же, извиняюсь за истинную неэлегантность): https://gist.github.com/tonyahowe/c55167e13ae22139f94080289cb88f47:

declare function tei2:tei2html($nodes as node()*) {
    for $node in $nodes
    return
        typeswitch ($node)
            case text() return
                $node
            case element(tei:TEI) return
                tei2:tei2html($node/*)
            case element(tei:teiHeader) return
                tei2:header($node) 
            case element(tei:frontTitle) return
                <h3>{ tei2:tei2html($node/node()) }</h3>
            case element(tei:lb) return
                <br>{ tei2:tei2html($node/node()) }</br>
            case element(tei:l) return
                <l>{ tei2:tei2html($node/node()) }</l>
            case element(tei:i) return
                <i>{ tei2:tei2html($node/node()) }</i>
            case element(tei:pb) return
                <span style="color:lightgray">[end page {tei2:tei2html($node/@n)}]{ tei2:tei2html($node/node()) }</span>
            case element(tei:footer) return
                <hr>{ tei2:tei2html($node/node()) }</hr>
            case element(tei:front) return
                tei2:front($node)
            case element(tei:rs) return 
                tei2:link($node)
            case element(tei:quote) return 
                tei2:link($node)
            case element(tei:note) return
               tei2:note($node) 
            case element(tei:footnote) return
                tei2:footnote($node)
            case element(tei:p) return
                <p xmlns="http://www.w3.org/1999/xhtml" id="{tei2:get-id($node)}">{ tei2:tei2html($node/node()) }</p> (: THIS IS WHERE THE ANCHORS ARE INSERTED! :)
            case element(exist:match) return
                <mark xmlns="http://www.w3.org/1999/xhtml">{ $node/node() }</mark>
            case element() return
                tei2:tei2html($node/node())
            default return
                $node/string() (: what would this catch? comment node in the xml? :)
};

declare function tei2:link($node as element()) {
  if ($node/@link ne '' and $node/@link castable as xs:anyURI) then 
    <a href="{$node/@link}" data-toggle="tooltip" title="{$node/@title}">{
      tei2:tei2html( $node/node() )
    }</a>
  else 
    tei2:tei2html( $node/node() )
};

declare function tei2:note($node as element()) {
    <span style="color:black" href="{$node/@link}" data-toggle="tooltip" title="{$node/@title}"> {
        tei2:tei2html ( $node/node() )
    }</span>
}; 

-------------------------- cut

declare function tei2:front($front as element (tei:front)) {
    let $titlePage := $front//tei:titlePage
    let $titlePart := $front//tei:titlePart
    let $epigraph := $front//tei:epigraph
    let $note := $front//tei:note
    let $argument := $front//tei:argument
    let $quote := $front//tei:quote
    let $bibl := $front//tei:bibl
    let $author := $front//tei:author
    
    return
        <div xmlns="http://www.w3.org/1999/xhtml" class="main-text-frontmatter">
        {   
            for $lb in $titlePage
            return 
                $titlePage//tei:lb
                
                    
            }
  
            {
                console:log($epigraph),
                for $cit in $epigraph
                return
                    <blockquote>
                        {
                            <a href="{$quote/@link}" data-toggle="tooltip" title="{$quote/@title}">{$quote/tei:l}</a>
                            
                        }<br/>

                        --
                            {
                                <a href="{$author/@link}" data-toggle="tooltip" title="{$author/@title}">{$author/text()}</a>
                            }
                    </blockquote>
            }
            </div>
};


person Tonya Howe    schedule 16.08.2016    source источник
comment
Я не вижу здесь никакого XSLT, вы хотели также использовать XSLT? Вам может показаться, что это проще, чем писать такой сложный переключатель типов в XQuery.   -  person adamretter    schedule 17.08.2016
comment
Обратите внимание, что это сайт вопросов и ответов, поэтому, если ответ помог вам, проголосуйте за него, и если он отвечает на ваш вопрос, примите его как ответ. Если у вас есть другие проблемы, вместо того, чтобы обновлять свой вопрос, опубликуйте новый, в идеале с новым кратким примером, демонстрирующим проблему. См. stackoverflow.com/help для получения дополнительной информации.   -  person wst    schedule 17.08.2016


Ответы (2)


Обычно в TEI элемент lb является пустым элементом этапа, поэтому он отображается только как: <lb/>. (См. Руководство TEI на lb. Он отмечает место разрыва строки, а не окружает все содержимое строки, как вы использовали его в TEI здесь.

Точно так же элемент HTML <br/> является пустым элементом. Таким образом, ваш typeswitch для этого элемента может превратиться в case element(tei:lb) return <br/>.

Приспособив разметку TEI к этой <lb/> форме и приспособив переключатель типов к нашим HTML-элементам <br/>, вы сможете найти решение.

person Joe Wicentowski    schedule 16.08.2016
comment
Да! Я пытался это сделать, но кажется, что переключатель типов работает над тем, чего нет в разделе <front> (который отправляется в функцию). Я буду продолжать работать над этим. Спасибо, Джо! - person Tonya Howe; 17.08.2016
comment
Хорошо, я так и сделал, и это помогло решить организационную проблему; Я также изменил функцию на { for $n in $titlePart return $titlePart/node() }. Трудность для меня заключается в том, чтобы существующая трансформация <epigraph> отображалась встроенной. - person Tonya Howe; 17.08.2016
comment
Спасибо, @joewiz! Я очень ценю это! - person Tonya Howe; 17.08.2016
comment
Конечно, Тоня, это не сильно помогло, поскольку это был не столько прямой ответ, сколько указание. Я был бы рад взглянуть поближе, если у вас все еще есть проблемы после работы с другими ответами здесь. Мы могли бы встретиться за чашечкой кофе как-нибудь, чтобы поработать над этим. - person Joe Wicentowski; 17.08.2016
comment
Спасибо, Джо, какое-то время я немного застрял, и это как бы подпитывало само себя... Мне бы не помешала помощь, но боюсь, это настолько просто, что вам надоест. - person Tonya Howe; 20.08.2016
comment
Никогда не скучно! ;) А пока отличная идея задавать вопросы здесь. - person Joe Wicentowski; 20.08.2016

Я не вижу, где вы преобразуете элементы lb в HTML:

for $lb in $titlePage
return 
    $titlePage//tei:lb

Это просто выгрузит XML TEI, который будет недопустимым HTML.

Похоже, что функция tei2:tei2html будет правильно отображать <lb> в HTML, но она также будет отображать <epigraph>, которые вы хотите исключить. Если ваш XML очень предсказуем и похож на ваш пример, вы можете исключить <lb>, содержащие epigraph, используя предикат:

$titlePage//tei:lb[not(tei:epigraph)]

Но это довольно ненадежно и также исключает <lb>, содержащие <epigraph>, смешанные с любыми текстовыми узлами, которые вы хотите сохранить. В этом случае вы можете рекурсивно обработать элементы, чтобы удалить их:

declare function local:remove-epigraph(
  $node as node()
) as node()*
{
  typeswitch ($node)
  case element(tei:epigraph) return ()
  case element() return element { node-name($node) } {
    for $n in $node/node()
    return local:remove-epigraph($node)
  }
  default return $node
};

...

$titlePage//tei:lb/local:remove-epigraph(.)

Обновление:

Если вы ДЕЙСТВИТЕЛЬНО хотите визуализировать элемент epigraph встроенным, то просто используйте функцию tei2:tei2html для их визуализации:

$titlePage//tei:lb/tei2:tei2html(.)
person wst    schedule 16.08.2016
comment
Я вижу - это помогает. Я также понял еще одну путаницу в своем предыдущем посте (я также отредактирую его, чтобы уточнить). Я хочу, чтобы <epigraph> появлялись везде, где они есть, в рамках существующей логики титульного листа, то есть в соответствии с существующими <lb>. Если я исключаю <epigraph>, как вы предлагаете — что кажется очень полезным, спасибо! — он просто будет пропущен, а затем появится внизу, где он сейчас. Я все еще ожидаю, что смогу использовать <xsl:template-match>, но я не знаю, как переключаться между xslt и xql. - person Tonya Howe; 17.08.2016
comment
@TonyaHowe Я обновил ответ, чтобы сохранить элементы эпиграфа (что намного проще). XQuery гораздо более явный, чем XSLT, который, по сути, автоматически обходит дерево. Вызов рекурсивного выражения типа tei2:tei2html очень похож на логику XSLT. - person wst; 17.08.2016
comment
Спасибо, @wst! Это становится там! - person Tonya Howe; 17.08.2016