Можно ли в XSLT выбирать значения из списка с уникальным идентификатором

У меня есть такие XML-данные:

<modifications>
  <modification>
    <revision>1</revision>
    <file action="modified">
      <filename>file1.cpp</filename>
    </file>
    <user>steve</user>
    <comment>updating file1 and file2</comment>
  </modification>
  <modification>
    <revision>1</revision>
    <file action="modified">
      <filename>file2.cpp</filename>
    </file>
    <user>steve</user>
    <comment>updating file1 and file2</comment>
  </modification>
  <modification>
    <revision>2</revision>
    <file action="modified">
      <filename>file1.cpp</filename>
    </file>
    <user>rob</user>
    <comment>reverting file1</comment>
  </modification>
</modifications>

Я использую переменную xsl: для выбора этих данных, а затем получаю следующий вывод:

steve   1   file1.cpp    modified   updating file1 and file2
steve   1   file2.cpp    modified   updating file1 and file2
rob     2   file1.cpp    modified   reverting file1

Есть ли способ выбрать только значения с уникальным идентификатором, в данном случае - ревизию? Я понимаю, что это будет означать, что я потеряю некоторые данные, в частности список измененных файлов, но меня это устраивает. Хотелось бы увидеть что-то вроде этого:

steve   1   updating file1 and file2
rob     2   reverting file1

Это для журнала круиз-контроля, который выводит отдельный элемент модификации для каждого файла, измененного в ревизии.


person robwirving    schedule 12.05.2015    source источник
comment
Вы используете XSLT 1.0 или 2.0?   -  person Mathias Müller    schedule 13.05.2015


Ответы (1)


Если вам нужны данные только из первого появления номера ревизии, то можно сделать выражение XPath для соответствия «модификациям, номер ревизии которых появляется впервые»:

modification[not(preceding::revision = revision)]

Однако, поскольку вышеупомянутое также будет соответствовать тегам ревизий, где бы они ни появлялись в (предыдущем) xml, вы можете указать критерии более точно, чтобы они соответствовали только «модификациям, номер ревизии которых появляется впервые при любой предыдущей модификации»:

modification[not(preceding-sibling::modification/revision = revision)]

Вот полный XML для этого:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" version="1.0" encoding="UTF-8"/>
    <!-- match modification tags with NEW revisions -->
    <xsl:template match="modification[not(preceding-sibling::modification/revision = revision)]">
        <xsl:value-of select="concat(user,'&#9;',revision,'&#9;',comment,'&#13;&#10;')"/>
    </xsl:template>
    <!-- ignore all other text -->
    <xsl:template match="text()"/>
</xsl:stylesheet>

Это дает желаемый результат:

steve   1   updating file1 and file2
rob     2   reverting file1
person MrWatson    schedule 12.05.2015
comment
Вам необходимо узнать о мюнхянской группировке, которая обеспечивает гораздо лучшее решение для XSLT. 1.0. В XSLT 2.0 это может быть выполнено с помощью <xsl:for-each-group> или distinct-values() функции. - person michael.hor257k; 12.05.2015