0

我在编写 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 中有一个条目,但未使用上述元素之一进行标记。我不知道如何处理这个问题。提前感谢您的帮助!

4

1 回答 1

0

我认为这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-stringXQuery 也支持它,并且可以使用一些带有 switch 的递归函数来模拟 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

于 2020-01-22T20:51:11.123 回答