XSL 2.0 — создание отдельных URL-адресов из вложенных элементов

У меня есть файлы tei-xml, в которых я пометил именованные объекты в средневековых документах, в частности имена людей, используя <persName/>. Простой пример:

<persName nymref="#Bernard_Faure_Senior">Bernardus Fabri senior</persName>

Однако в рукописи часто встречаются имена, где мне нужно сделать пометку «Raimunda uxor Bernardi Fabri» (т.е. «Раймунда, жена Бернара Фора»). Здесь я размечаю оба имени во вложенном виде:

<persName nymref="#Raimunda_Faure">Raimunda uxor 
   <persName nymref="#Bernard_Faure_Senior">Bernardi Fabri 
                       senior</persName></persName>

Как правило, это не проблема для запроса данных. Однако я хочу вывести через XSLT 2.0 следующее для веб-страницы, где каждое имя превращается в URL-адрес, указывающий на собственную веб-страницу этого человека (используя @nymRef). Вышеприведенное должно вывести это:

 <a href="www.foo.com/person/Raimunda_Faure">Raimunda 
        uxor</a><a href="www.foo.com/person/Bernard_Faure_Senior">Bernardi 
       Fabri<a>

(т.е. ...etiam nec tortor erat Raimunda uxor Bernardi Fabri est leo cursus magna, maximus finibus...)

Более того, бывают случаи, когда происходит следующее (два имени, вложенных в одно):

 <persName nymref="#Raimunda_Faure">Raimunda uxor 
   <persName nymref="#Bernard_Faure_Senior">Bernardi Fabri 
                       senior</persName> matris 
   <persName nymRef="Bernard_Faure_Junior">Bernardi 
                       junior</persName></persName>

(Хотя никогда не бывает случая, когда <persName> вложен в три раза)

Я совершенно не понимаю, как рекурсивно различать и обрабатывать //persName[x] и //persname[x]//persName[x], чтобы сделать их отдельными URL-адресами.

URL-адрес генерируется из статического значения + after-substring(//tei:persName/@nymRef,'#'). Очевидно, что простой оператор XSL возвращает ошибку кардинальности:

concat('www.foo.com/person',after-substring(//tei:persName/@nymRef,'#'))

Заранее большое спасибо за любую помощь.


person jbrehr    schedule 16.10.2018    source источник


Ответы (1)


Предполагая, что ваш XML выглядит так...

<persName nymref="#Raimunda_Faure">Raimunda uxor 
   <persName nymref="#Bernard_Faure_Senior">Bernardi Fabri senior</persName> matris   
   <persName nymRef="Bernard_Faure_Junior">Bernardi junior</persName>
</persName>

Затем вы можете достичь своей цели, добавив этот шаблон в свой XSLT.

<xsl:template match="persName">
  <a href="www.foo.com/person/{substring-after(@nymref, '#')}">
    <xsl:value-of select="text()[1]" />
  </a>
  <xsl:apply-templates select="node()[position() > 1]" />
</xsl:template>

(Хотя, если вы имеете дело с TEI, вам нужно будет учитывать пространства имен).

Это предполагает отсутствие других типов тегов в имени.

РЕДАКТИРОВАТЬ: Если в имени есть другие теги, попробуйте вместо этого этот шаблон, который будет обертывать все до первого persName в теге a

<xsl:template match="persName">
  <xsl:variable name="nested" select="persName[1]|persName[1]/following-sibling::node()" />
  <a href="www.foo.com/person/{substring(@nymref, 2)}">
    <xsl:apply-templates select="node() except $nested" />
  </a>
  <xsl:apply-templates select="$nested" />
</xsl:template>  
person Tim C    schedule 16.10.2018
comment
Возможно, в имени есть другие теги... чтобы их игнорировать :/ Но это можно как-то добавить к предикату? <xsl:apply-templates select="node()[name() = 'persName' and position() > 1]" /> ? - person jbrehr; 16.10.2018
comment
Я внес изменения в свой вопрос, чтобы показать, что это возможно сделать. - person Tim C; 16.10.2018
comment
Работает идеально! (в конце концов я выясню, как это работает... ;)) - person jbrehr; 16.10.2018