мюнхенская группировка - PullRequest
       31

мюнхенская группировка

3 голосов
/ 21 ноября 2011

Мне было интересно, как этот предикат ([1]) жестко закодирован как 1 всегда в группировке мюнхенов.Концепция была неясна для меня после долгих поисков.Поясняется, что текущий узел сравнивается с 1-й группой, возвращаемой ключом.Почему он всегда сравнивается с первым, которому соответствует ключ?Также, почему мы даем contact[count(. | key('contacts-by-surname', surname)[1]) = 1], the =1 part? снова, 1 жестко закодирован.Я сослался на ссылку ниже

http://www.jenitennison.com/xslt/grouping/muenchian.html

Ответы [ 3 ]

2 голосов
/ 21 ноября 2011

Скажем, у нас есть определение ключа <xsl:key name="contacts-by-surname" match="contact" use="surname"/>, тогда выражение key('contacts-by-surname', 'Doe') дает вам набор узлов со всеми contact элементами, где surname равно Doe. Выражение key('contacts-by-surname', 'Doe')[1] дает вам первое contact в этой «группе».

Теперь при обработке всех элементов contact с помощью for-each или apply-templates мы обычно хотим найти способ идентифицировать первый элемент contact в каждой группе. Это может быть достигнуто с помощью <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[1]) = 1]"> или <xsl:for-each select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]">.

Если ваше требование отличается и вы, например, хотели идентифицировать последний элемент в каждой группе, тогда вы, конечно, можете использовать другой предикат, как в <xsl:for-each select="contact[count(. | key('contacts-by-surname', surname)[last()]) = 1]"> или <xsl:for-each select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[last()])]">.

1 голос
/ 21 ноября 2011

Мне было интересно, как этот предикат ([1]) закодирован как 1 всегда в мюнхенская группировка.

Это просто :

Функция key() создает все узлы для данной группы, и мы хотим взять только один узел из любой группы.

Не гарантируется, что во всех группах будет два или более узлов - у некоторых может быть только один узел.

Вот почему безопасно и удобно брать первый (и, возможно, единственный) узел из каждой группы.

Мы могли бы с тем же успехом выполнить группировку, взяв последний узел из каждой группы (но это будет менее эффективно):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kNumByMod3" match="num"
  use=". mod 3"/>

 <xsl:template match=
  "num[generate-id()
      =
       generate-id(key('kNumByMod3', . mod 3)[last()])
      ]
  ">


  3k + <xsl:value-of select=". mod 3"/>:
<xsl:text/>
  <xsl:copy-of select="key('kNumByMod3', . mod 3)"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

при применении к этому документу XML :

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

дает желаемый, правильно сгруппированный результат :

  3k + 2:
<num>02</num>
<num>05</num>
<num>08</num>


  3k + 0:
<num>03</num>
<num>06</num>
<num>09</num>


  3k + 1:
<num>01</num>
<num>04</num>
<num>07</num>
<num>10</num>
0 голосов
/ 21 ноября 2011

Основной алгоритм состоит в том, что есть два вложенных цикла.Внешний цикл выбирает один репрезентативный узел из каждой группы, а внутренний цикл выбирает все узлы в этой группе (включая один, выбранный в качестве репрезентативного)Самый простой способ выбрать один репрезентативный узел из группы - это выбрать первый, отсюда и предикат [1].

...