#xslt #xslt-2.0 #xslt-grouping #xslt-3.0
#xslt #xslt-2.0 #xslt-группировка #xslt-3.0
Вопрос:
У меня есть фрагмент кода, который выглядит следующим образом:
<root>
<applicant>
<id>XYZ</id>
<group>
<start_date>2019-04-01</start_date>
<end_date>2019-04-01</end_date>
</group>
<group>
<start_date>2019-04-02</start_date>
<end_date>2019-04-02</end_date>
</group>
<group>
<start_date>2019-04-03</start_date>
<end_date>2019-04-03</end_date>
</group>
</applicant>
<applicant>
<id>ABC</id>
<group>
<start_date>2019-05-01</start_date>
<end_date>2019-05-01</end_date>
</group>
<group>
<start_date>2019-05-02</start_date>
<end_date>2019-05-02</end_date>
</group>
<group>
<start_date>2019-05-03</start_date>
<end_date>2019-05-03</end_date>
</group>
</applicant>
</root>
и мне нужно сгруппировать его по кандидатам и объединить в один узел с единой датой начала и датой окончания, если дата от следующего родного брата отличается на 1 день (разница в днях равна 1)
итак, для приведенного выше кода для достижения чего-то вроде:
<root>
<applicant>
<id>XYZ</id>
<start_date>2019-04-01</start_date>
<end_date>2019-04-03</end_date>
</applicant>
<applicant>
<id>ABC</id>
<start_date>2019-05-01</start_date>
<end_date>2019-05-03</end_date>
</applicant>
</root>
Я думал об использовании следующего-sibling:: или какого-то повторения.
Комментарии:
1. Если вы действительно можете использовать XSLT 2.0 или 3.0, то я бы удалил тег XSLT-1.0 из вопроса, чтобы уточнить, какую версию вы можете использовать (особенно потому, что любое решение XSLT 1.0 было бы совсем непростым). Спасибо!
Ответ №1:
Предполагая, что вы действительно можете использовать XSLT 2.0 или выше, вы могли бы использовать xsl:for-each-group
here и group, начиная с элементов, которые start_date - 1
не соответствуют end_date
предыдущей группе.
Попробуйте этот XSLT
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes" />
<xsl:template match="applicant">
<xsl:copy>
<xsl:copy-of select="id" />
<xsl:for-each-group select="group" group-starting-with="group[not(xs:date(start_date) - xs:dayTimeDuration('P1D') = xs:date(preceding-sibling::group[1]/end_date))]">
<group>
<xsl:copy-of select="start_date, current-group()[last()]/end_date" />
</group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
(Для этого используется XSLT 3.0. В XSLT 2.0 все, что вам нужно сделать xsl:mode
, это заменить шаблон идентификатора на)
Комментарии:
1. Очень хороший ответ. Я думаю, что следует что-то сказать об использовании такого специального условия, чтобы не иметь первой несоответствующей группы.