0

我的 XML 文件具有 TEI 里程碑元素,例如<handShift new="#DP1053/>;内容的开头总是有一个<text>,但之后有时会有一些此类标签,其中两个或三个不同的属性值之一散布在<text>元素中,以指示特定抄写员在最后一个之后拾取的位置。属性的值@new指向@xml:idTEI 头中的定义,注册为<handNote/>元素的属性。

我在 XSLT 2.0 中的目标是连接每个抄写员编写的文本,以便我可以独立查询每个抄写员的工作。我想知道推荐的解决方案是否需要group-starting-with,但我还没有完全理解所涉及的预处理(我将不胜感激指针)。相反,我自己的直觉是执行

  • 一个for-each循环遍历抄写员的手,运行
  • 一个string-join
  • 在所有文本节点上
  • 其中,与当前循环迭代中处理的手相匹配的<handShift/>属性值的前一个比属性值不匹配的前一个更接近。@new<handShift/>

我在转换为 HTML 的 XSLT 2.0 样式表中的试用语法如下:

<xsl:for-each select="//tei:handNote[@xml:id != '']">
    <xsl:variable name="hand" select="./@xml:id"/>
    <p><xsl:value-of select="$hand"/>: <xsl:value-of select="string-join(//tei:text//text()[preceding-sibling::tei:handShift[@new = concat('#',$hand)] &gt;&gt; preceding-sibling::tei:handShift[@new != concat('#',$hand)]])"/></p>
</xsl:for-each>

但是,这仅返回文本中最终里程碑之后的文本节点,并且仅在为匹配该最终里程碑的属性值选择的 for-each 迭代中。我肯定把>>陈述弄错了,对于这种方法或不同的基于分组的方法的任何建议,我将不胜感激。

我可能应该提到,一旦我掌握了这种串联,我将不得不<add hand="DP1054">addition</add>通过排除这种性质的不匹配内容并包括匹配来将任何类型的内容(即手工修改与当前限制不匹配)添加到等式中位于不匹配的抄写员范围内的内容,但我不一定预见到必须将其添加到“正确”位置的串联中。因此,我应该能够通过两个相当简单的附加步骤来解决这些问题,但最初的串联或分组解决方案必须允许排除具有不匹配属性值的节点,以及我可能希望排除的任何其他元素(例如<expan>在下面的例子)。

这是一个模拟 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE TEI>
<TEI>
 <teiHeader>
  <fileDesc/>
   <sourceDesc>
    <msDesc>
     <physDesc>
      <handDesc>
       <handNote xml:id="DP1054"/>
       <handNote xml:id="DP1053"/>
      </handDesc>
     </physDesc>
    </msDesc>
   </sourceDesc>
 </teiHeader>
 <text>
  <body>
    <p><handShift new="#DP1054"/>I'LL REPRESENT THE WORK OF HAND 1054 IN ALLCAPS <handShift new="#DP1053"/>and I'll represent the work of hand 1053 in lowercase <handShift new="#DP1054"/>THE IDEA BEING THAT IN THE END ALL UPPERCASE TEXT SHOULD BE CONCATENATED <handShift new="#DP1053"/>separately from the sentence case content. Of course reality is a little more <add hand="#DP1054">COMPLEX</add>: we have <hi rend="color(green)">other nodes intervening</hi>, <handShift new="#DP1054"/>AND I WONDER WHETHER THESE WILL MESS WITH THE CONCEPT OF <choice>
     <abbr>SBLS</abbr>
     <expan>S<ex>I</ex>BL<ex>ING</ex>S</expan>
    </choice> <handShift new="#DP1053"/> (I will filter out nodes with `tei:expan` ancestors and nonmatching `add` elements; that's not the part I am having difficulty with).</p>
  </body>
 </text>
</TEI>
4

1 回答 1

0

我认为 group-starting-with 可以提供帮助,这是一个将结果存储在 XPath 3.1 映射中的示例(好吧,分组给出了一系列映射,并且map:merge函数在 handShift 之后将它们合并为从 id 到节点的单个映射那个id):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.tei-c.org/ns/1.0"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:variable name="note-map-sequence" as="map(xs:string, node()*)*">
      <xsl:for-each-group select="//body/p/node()" group-starting-with="handShift">
          <xsl:map-entry key="substring(@new, 2)" select="current-group()"/>
      </xsl:for-each-group>
  </xsl:variable>

  <xsl:variable name="note-map" as="map(xs:string, node()*)"
    select="map:merge($note-map-sequence, map { 'duplicates' : 'combine' })"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
      </head>
      <body>
        <xsl:apply-templates select="//handNote"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="handNote">
      <p>
        <xsl:value-of select="@xml:id"/>: 
        <xsl:apply-templates select="$note-map(@xml:id)"/>
      </p>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFWRApk有一个在线示例输出

<!DOCTYPE HTML>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>.NET XSLT Fiddle Example</title></head>
   <body>
      <p>DP1054: 
         I'LL REPRESENT THE WORK OF HAND 1054 IN ALLCAPS THE IDEA BEING THAT IN THE END ALL UPPERCASE TEXT SHOULD BE CONCATENATED AND I WONDER WHETHER THESE WILL MESS WITH THE CONCEPT OF 
         SBLS
         SIBLINGS

      </p>
      <p>DP1053: 
         and I'll represent the work of hand 1053 in lowercase separately from the sentence case content. Of course reality is a little more COMPLEX: we have other nodes intervening,  (I will filter out nodes with `tei:expan` ancestors and nonmatching `add` elements;
         that's not the part I am having difficulty with).
      </p>
   </body>
</html>

带有 XPath 3.1 的 XSLT 3 从 Saxon 9.8 开始可用,因此大多数使用 Saxon 9 的 XSLT 2 应该能够通过使用最新 (9.9) 或以前 (9.8) 版本的 Saxon 来使用 XSLT 3。

当然,地图只是作为分组结果的优雅和轻量级容器,使用的for-each-group也可以与 XSLT 2 一起使用,只是您需要将分组结果存储在一些中间 XML(例如<group id="{current-grouping-key()}">...</group>)中。

于 2020-02-19T17:33:18.510 回答