XSL 2.0 - generating distinct urls from nested ele

2019-08-20 05:18发布

I have tei-xml files where I've marked up named entities within medieval documents, in particular people's names using <persName/>. A simple example:

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

However, there are often names in the manuscript where I need to mark up "Raimunda uxor Bernardi Fabri" (ie "Raimunda, wife of Bernard Faure"). Here I markup both names, in nested fashion:

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

Generally this isn't a problem for querying the data. However, I want to output via XSLT 2.0 the following for a webpage, where each name is turned into a URL pointing to that person's own webpage (using @nymRef). The above should output to this:

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

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

Moreover, there are times where the following occurs (two names nested in one):

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

(Although there is never a case where <persName> is nested three-deep)

I'm utterly lost as to how recursively differentiate and treat //persName[x] and //persname[x]//persName[x] in order to make them separate URLs.

The url is generated from a static value + after-substring(//tei:persName/@nymRef,'#'). Obviously a simple XSL statement returns a cardinality error:

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

Many thanks in advance for any assistance.

标签: xslt tei
1条回答
再贱就再见
2楼-- · 2019-08-20 05:55

Assuming your XML looked like this...

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

Then you could achieve your aim by adding this template to your 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>

(Although if you are dealing with TEI, you would need to account for namespaces).

This does assume no other types of tags in the name.

EDIT: If there are other tags in the name, try this template instead, which will wrap everything before the first persName in the a tag

<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>  
查看更多
登录 后发表回答