Объединить текстовые узлы по элементам вехи, используя XSLT 2.0 - PullRequest
0 голосов
/ 19 февраля 2020

Мои XML файлы содержат элементы этапа TEI, такие как <handShift new="#DP1053/>; всегда есть один в начале содержимого <text>, но после этого иногда есть несколько таких тегов с одним или двумя или тремя различными значениями атрибута, разбросанными по элементу <text>, чтобы указать, где конкретный писец забирает после последнего Значение атрибута @new указывает на определение @xml:id в заголовке TEI, зарегистрированное как атрибут элемента <handNote/>.

Моя цель в XSLT 2.0 - объединить текст, написанный каждым писцом. так что я могу запросить работу каждого писца независимо. Интересно, повлечет ли за собой рекомендованное решение group-starting-with, но я еще не обернул голову вокруг предварительной обработки (я был бы благодарен за указатели). Вместо этого мой собственный инстинкт состоит в том, чтобы выполнить

  • a for-each l oop, перебирая руки писца, выполняя
  • a string-join
  • на всех текстовые узлы
  • , где предшествующий <handShift/> со значением атрибута @new, совпадающим с рукой, обработанной в текущей итерации l oop, на ближе , чем предшествующий <handShift/>, где значение атрибута не совпадает.

Мой пробный синтаксис в таблице стилей XSLT 2.0 с преобразованием в HTML выглядит следующим образом:

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

Однако это возвращает только текстовый узел ( s) после последнего этапа в тексте и только для каждой итерации, которая выбирает значение атрибута, соответствующее этому последнему этапу. Я, безусловно, ошибся в утверждении >> и буду благодарен за любые советы, связанные с этим подходом или с другим подходом, основанным на группировке.

Я должен упомянуть, что, как только я справлюсь с этой конкатенацией Мне нужно будет добавить в уравнение любой контент <add hand="DP1054">addition</add> -типа (т. Е. Ревизии руками, не совпадающими с текущими ограничениями) в уравнение, исключив несоответствующий контент такого рода и включив соответствующий контент, находящийся в несоответствующих строчках, но я не обязательно предвидеть, что это необходимо добавить в конкатенацию в «правильном» месте. Таким образом, я должен иметь возможность учесть это в двух довольно простых дополнительных шагах, но первоначальное решение для конкатенации или группировки должно учитывать исключение узлов с несоответствующими значениями атрибутов и любых других элементов, которые я могу исключить (1045 *) ( например, <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>

1 Ответ

0 голосов
/ 19 февраля 2020

Я думаю, что может помочь начало группы, вот пример, в котором результат сохраняется в карте XPath 3.1 (ну, группировка дает последовательность карт, а функции map:merge объединяют их в одну карту из id на узлы после handShift этого идентификатора):

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

XSLT 3 с XPath 3.1 доступен с Saxon 9.8, поэтому большинство людей, использующих Saxon 9 для XSLT 2, должны также иметь возможность использовать XSLT 3, используя самую последнюю (9.9) или предыдущую (9.8) версию Saxon.

Конечно, карта служит только как элегантный и легкий контейнер для результатов группировки, использованный for-each-group может использоваться и с XSLT 2, только вам нужно будет хранить результат группировки в некотором посреднике XML (например, <group id="{current-grouping-key()}">...</group>).

...