Применение фильтра дат для каждого родителя, содержащего дату начала и окончания, с использованием XSLT

#xml #xslt

Вопрос:

Я пытаюсь преобразовать следующий xml таким образом, чтобы:

  1. текущие входные данные копируются для каждой уникальной даты начала в xml (и группируются по этой дате начала).
  2. каждая созданная структура CompoundEmployee содержит только те родительские узлы, для которых дата начала группы находится в диапазоне ее дочерних дат начала и окончания.

Ввод:

 <queryCompoundEmployeeResponse>
    <CompoundEmployee>
        <employment_information>
            <start_date>2021-11-01</start_date>
            <end_date>9999-12-31</end_date>
            <job_information>
                <start_date>2021-12-01</start_date>
                <end_date>9999-12-31</end_date>
            </job_information>
            <job_information>
                <start_date>2021-11-01</start_date>
                <end_date>2021-11-30</end_date>
            </job_information>
        </employment_information>
        <employment_information>
            <start_date>2021-03-01</start_date>
            <end_date>2021-10-31</end_date>
            <job_information>
                <start_date>2021-05-01</start_date>
                <end_date>2021-10-31</end_date>
            </job_information>
            <job_information>
                <start_date>2021-03-01</start_date>
                <end_date>2021-04-30</end_date>
            </job_information>
        </employment_information>
    </CompoundEmployee>
</queryCompoundEmployeeResponse>
 

XSLT:

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

    <xsl:template match="//CompoundEmployee">
        <queryCompoundEmployeeResponse>
            <xsl:for-each-group select="." group-by="//start_date">
                <xsl:sort select="current-grouping-key()"/>
                <start_date date="{current-grouping-key()}">
                    <xsl:for-each select="current-group()">
                        <CompoundEmployee>
                            <xsl:copy-of select="./*[start_date amp;<= current-grouping-key() and end_date amp;> current-grouping-key()]"/>
                        </CompoundEmployee>
                    </xsl:for-each>
                </start_date>
            </xsl:for-each-group>
        </queryCompoundEmployeeResponse>
    </xsl:template>
    
</xsl:stylesheet>
 

Текущий вывод, который генерируется, близок к тому, что я хочу: каждая группа содержит только один узел информации о занятости, где дата начала группы находится в диапазоне даты начала и окончания информации о занятости. Однако то же самое не происходит для узлов job_information в employment_information:

 <queryCompoundEmployeeResponse>
    <start_date date="2021-03-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-03-01</start_date>
                <end_date>2021-10-31</end_date>
                <job_information>
                    <start_date>2021-05-01</start_date>
                    <end_date>2021-10-31</end_date>
                </job_information>
                <job_information>
                    <start_date>2021-03-01</start_date>
                    <end_date>2021-04-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-05-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-03-01</start_date>
                <end_date>2021-10-31</end_date>
                <job_information>
                    <start_date>2021-05-01</start_date>
                    <end_date>2021-10-31</end_date>
                </job_information>
                <job_information>
                    <start_date>2021-03-01</start_date>
                    <end_date>2021-04-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-11-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-11-01</start_date>
                <end_date>9999-12-31</end_date>
                <job_information>
                    <start_date>2021-12-01</start_date>
                    <end_date>9999-12-31</end_date>
                </job_information>
                <job_information>
                    <start_date>2021-11-01</start_date>
                    <end_date>2021-11-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-12-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-11-01</start_date>
                <end_date>9999-12-31</end_date>
                <job_information>
                    <start_date>2021-12-01</start_date>
                    <end_date>9999-12-31</end_date>
                </job_information>
                <job_information>
                    <start_date>2021-11-01</start_date>
                    <end_date>2021-11-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
</queryCompoundEmployeeResponse>
 

How do I need to change my XSLT so that each employment_information node contains only the one job_information node where the group startdate is within its start-enddate range? It’s possible for the XML to contain deeper levels of nesting and differently named nodes (each containing a start and enddate), so I’d like to avoid explicit references to «employment_information» and «job_information».

Expected output:

 <queryCompoundEmployeeResponse>
    <start_date date="2021-03-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-03-01</start_date>
                <end_date>2021-10-31</end_date>
                <job_information>
                    <start_date>2021-03-01</start_date>
                    <end_date>2021-04-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-05-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-03-01</start_date>
                <end_date>2021-10-31</end_date>
                <job_information>
                    <start_date>2021-05-01</start_date>
                    <end_date>2021-10-31</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-11-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-11-01</start_date>
                <end_date>9999-12-31</end_date>
                <job_information>
                    <start_date>2021-11-01</start_date>
                    <end_date>2021-11-30</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
    <start_date date="2021-12-01">
        <CompoundEmployee>
            <employment_information>
                <start_date>2021-11-01</start_date>
                <end_date>9999-12-31</end_date>
                <job_information>
                    <start_date>2021-12-01</start_date>
                    <end_date>9999-12-31</end_date>
                </job_information>
            </employment_information>
        </CompoundEmployee>
    </start_date>
</queryCompoundEmployeeResponse>