как объединить / сгруппировать XML-документ на основе дочернего узла - PullRequest
0 голосов
/ 05 июня 2019

Интересно, как объединить / сгруппировать / объединить XML-элементы по их содержимому, чтобы сгруппированные значения встречались только один раз, а остальная часть узла была объединена в результат, как если бы можно было группировать результаты в современных SQL-диалектах, таких какMariaDB (без дубликатов в результатах).

Я уже искал решение, но приведенные здесь примеры или где-то еще не соответствуют моим требованиям - также не после их корректировки.Я думаю, что позиция <lemma> может быть проблемой.С другой стороны, я думаю / надеюсь, что решение все равно будет возможно.

Упрощенная структура моих документов и желаемый результат:

XML:

<root>
  <artikel>
    <lemma-position>
      <lemma>Abend</lemma>
      <info>aaa</info>
    </lemma-position>
    <bedeutungsposition nr="1a">
      <bedeutung>Zeit am Ende des Tages</bedeutung>
    </bedeutungsposition>
    <bedeutungsposition nr="1b">
      <bedeutung>
        was anderes
      </bedeutung>
    </bedeutungsposition>
  </artikel>
  <artikel>
    <lemma-position>
      <lemma>Abend</lemma>
      <info>bbb</info>
    </lemma-position>
    <bedeutungsposition nr="1">
      <bedeutung>abcdefg</bedeutung>
    </bedeutungsposition>
    <bedeutungsposition nr="2">
      <bedeutung>japoisdfoiasjdfoasjdfl</bedeutung>
    </bedeutungsposition>
  </artikel>
</root>

В этом примере узел <lemma> содержит«Абенд», и это должно быть значение для группировки.

желаемый вывод:

<root>
  <artikel>
    <lemma-position>
      <lemma>Abend</lemma>
      <info>aaa</info>
      <info>bbb</lemma>
    </lemma-position>
    <bedeutungsposition nr="1">
      <bedeutung>abcdefg</bedeutung>
    </bedeutungsposition>
    <bedeutungsposition nr="1a">
      <bedeutung>Zeit am Ende des Tages</bedeutung>
    </bedeutungsposition>
    <bedeutungsposition nr="1b">
      <bedeutung>
        was anderes
      </bedeutung>
    </bedeutungsposition>
    <bedeutungsposition nr="2">
      <bedeutung>japoisdfoiasjdfoasjdfl</bedeutung>
    </bedeutungsposition>
  </artikel>
</root>

То, что я получаю, представляет собой неотправленную копию, то есть XML-вход, или его часть, но не объединенную вообще.Я уже пробовал несколько вещей, из которых база всегда выглядит примерно так:

<xsl:template match="/">
  <xsl:copy>
    <xsl:for-each-group select="artikel" group-by="//lemma">
      <xsl:copy-of select="current-group()//lemma/*" />
      <!--
        I also placed some other paths and expressions here or above to 
        select the elements differently, without success however.  
      -->
    </xsl:for-each-group>

  </xsl:copy>
</xsl:template>

Я также пробовал xQuery с distinct-values и т. Д., Но он также не работал (без дубликатов).

Я тестирую с Oxygen и baseX, оба подключаются к Saxon-9.8 HE, так что на самом деле все должно быть хорошо.Решение в XSLT будет цениться так же, как и в xQuery

1 Ответ

3 голосов
/ 05 июня 2019

Я думаю, что основной шаблон будет

  <xsl:template match="root">
      <xsl:copy>
          <xsl:for-each-group select="artikel" group-by="lemma-position/lemma">
              <xsl:copy>
                  <lemma-position>
                      <lemma>
                          <xsl:value-of select="current-grouping-key()"/>
                      </lemma>
                      <xsl:apply-templates select="current-group()/lemma-position/(* except lemma)"/>
                  </lemma-position>
                  <xsl:apply-templates select="current-group()/(* except lemma-position)">
                      <xsl:sort select="@nr"/>
                  </xsl:apply-templates>
              </xsl:copy>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

вместе с преобразованием идентичности (например, в XSLT 3, объявленном xsl:mode on-no-match="shallow-copy") вы получаете https://xsltfiddle.liberty -development.net / gWvjQfR :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="#all"
    version="3.0">

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="root">
      <xsl:copy>
          <xsl:for-each-group select="artikel" group-by="lemma-position/lemma">
              <xsl:copy>
                  <lemma-position>
                      <lemma>
                          <xsl:value-of select="current-grouping-key()"/>
                      </lemma>
                      <xsl:apply-templates select="current-group()/lemma-position/(* except lemma)"/>
                  </lemma-position>
                  <xsl:apply-templates select="current-group()/(* except lemma-position)">
                      <xsl:sort select="@nr"/>
                  </xsl:apply-templates>
              </xsl:copy>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

В BaseX XQuery вы можете использовать

<root>
{
    for $artikel in root/artikel
    group by $lemma := $artikel/lemma-position/lemma
    return
        <artikel>
           <lemma-position>
             <lemma>{$lemma}</lemma>
             {
                 $artikel/lemma-position/(* except lemma)
             }
           </lemma-position>
           {
               sort($artikel/(* except lemma-position), (), function($el) { $el/@nr })
           }
        </artikel>
}
</root>
...