xQuery: найти неаннотированный текст в TEI - PullRequest
0 голосов
/ 22 января 2020

У меня проблема с написанием xQuery. У меня есть коллекция писем в TEI, и каждый человек, организация и место в тексте должны быть в <persName>, <placeName> или <orgName>. У меня также есть список ключей XML с такими записями, как

<place xml:id="O_02">
    <placeName>
        <settlement>Kairo</settlement>
        <settlement>Cairo</settlement>
    </placeName>
    <link target="https://de.wikipedia.org/wiki/Kairo"/>
</place>

Большинство элементов в тексте уже аннотированы, но теперь мне нужно написать xQuery, чтобы найти части текста в буквы, которые имеют запись в KeyList, но не помечены одним из элементов выше. Я понятия не имею, как решить эту проблему. Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 22 января 2020

Я думаю, что analyze-string может помочь, вот прототип, использующий XSLT 3:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    expand-text="yes"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="key-list">
<place xml:id="O_02">
    <placeName>
        <settlement>Kairo</settlement>
        <settlement>Cairo</settlement>
    </placeName>
    <link target="https://de.wikipedia.org/wiki/Kairo"/>
</place>
  </xsl:param>

  <xsl:key name="ref" match="place/placeName/*" use="."/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="*[not(self::persName | self::placeName | self::orgName)]/text()">
      <xsl:apply-templates select="analyze-string(., '\p{L}+')" mode="wrap"/>
  </xsl:template>

  <xsl:template mode="wrap" match="fn:match[key('ref', ., $key-list)]">
      <xsl:element name="{key('ref', ., $key-list)/../node-name()}">{.}</xsl:element>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bwe3bL

У меня нет моего XQuery в настоящее время, но analyze-string поддерживается и в XQuery, и возможно использование некоторых рекурсивных функций с переключателем для эмуляции XSLT apply-templates:

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method 'xml';

declare variable $key-list as document-node() := document {
<place xml:id="O_02">
    <placeName>
        <settlement>Kairo</settlement>
        <settlement>Cairo</settlement>
    </placeName>
    <link target="https://de.wikipedia.org/wiki/Kairo"/>
</place>    
};

declare function local:key($value, $key-list as document-node()) as element()? {
  $key-list/place/placeName[settlement = $value]  
};

declare function local:apply-templates($nodes as node()*) as node()* {
  for $node in $nodes
  return typeswitch ($node)
        case element() return element { node-name($node) } { local:apply-templates($node!(@*, node())) }
        case text() return 
            if (not($node[parent::placeName | parent::persName | parent::orgName]))
            then local:wrap(analyze-string($node, '\p{L}+'))
            else $node
        default return $node
};

declare function local:wrap($nodes as node()*) as node()* {
   for $node in $nodes
   return typeswitch($node)
        case element(fn:match) return
            let $ref := local:key($node, $key-list)
            return
                if ($ref)
                then element { node-name($ref) } { data($ref) }
                else text { data($node) }
        case text() return $node
        default return local:wrap($node/node())
};

local:apply-templates(node())

https://xqueryfiddle.liberty-development.net/3Nzd8bN

...