使用 `<xsl:apply-templates>` 排序后缺少一些子节点
Posted
技术标签:
【中文标题】使用 `<xsl:apply-templates>` 排序后缺少一些子节点【英文标题】:Missing some child nodes after sorting with `<xsl:apply-templates>` 【发布时间】:2021-03-15 08:26:58 【问题描述】:我正在尝试根据字段 start_date 对子节点进行排序。在下面的 XML 节点 <employment_information>
中有两个子节点 <job_information>
,start_date 需要升序。
经过大量搜索和尝试,我的排序工作正常,但我遇到的问题是<employment_information>
中的其他字段消失了。节点<job_information>
的顺序正确,但其他字段已消失。
我的 XML:
<queryCompoundEmployeeResponse>
<CompoundEmployee period_start="2020-09-30" period_end="2020-12-03">
<id>347</id>
<type>CompoundEmployee</type>
<swHire>Y</swHire>
<swRehire>N</swRehire>
<swRetire>N</swRetire>
<person>
<action>NO CHANGE</action>
<country_of_birth>NLD</country_of_birth>
<created_by>admin_nm</created_by>
<created_on_timestamp>2018-05-02T14:03:25.000Z</created_on_timestamp>
<person_id>347</person_id>
<person_id_external>10160</person_id_external>
<place_of_birth>aaa</place_of_birth>
<employment_information>
<action>NO CHANGE</action>
<assignment_class>ST</assignment_class>
<created_by>admin_nm</created_by>
<created_on_timestamp>2018-05-02T14:03:25.000Z</created_on_timestamp>
<direct_reports>12</direct_reports>
<employment_id>347</employment_id>
<hiringNotCompleted>false</hiringNotCompleted>
<isContingentWorker>false</isContingentWorker>
<jobNumber>1</jobNumber>
<last_modified_by>aaa</last_modified_by>
<last_modified_on>2019-09-05T10:38:50.000Z</last_modified_on>
<originalStartDate>1992-05-01</originalStartDate>
<serviceDate>1992-05-01</serviceDate>
<start_date>1992-05-01</start_date>
<user_id>10160</user_id>
<job_information>
<action>CHANGE</action>
<shift_factor>0.0</shift_factor>
<shift_rate>0.0</shift_rate>
<standard_hours>38.0</standard_hours>
<start_date>2020-10-10</start_date>
<time_recording_admissibility_code>NL</time_recording_admissibility_code>
<time_recording_profile_code>NL</time_recording_profile_code>
<time_recording_variant>DURATION</time_recording_variant>
<time_type_profile_code>NL20+/CI+</time_type_profile_code>
<timezone>Europe/Amsterdam</timezone>
<workingDaysPerWeek>5.0</workingDaysPerWeek>
<workschedule_code>DUMMY</workschedule_code>
</job_information>
<job_information>
<shift_factor>0.0</shift_factor>
<shift_rate>0.0</shift_rate>
<standard_hours>0.0</standard_hours>
<start_date>2020-10-01</start_date>
<timezone>Europe/Amsterdam</timezone>
<workingDaysPerWeek>0.0</workingDaysPerWeek>
</job_information>
<job_event_information>
<action>INSERT</action>
<created_on_timestamp>2020-08-01T20:00:48.000Z</created_on_timestamp>
<event>5</event>
<event_date>2020-08-01</event_date>
<event_reason>DATACHG</event_reason>
<seq_number>1</seq_number>
</job_event_information>
</employment_information>
</person>
<execution_timestamp>2020-08-17T14:00:48.000Z</execution_timestamp>
<version_id>2005P0</version_id>
</CompoundEmployee>
</queryCompoundEmployeeResponse>
我使用的 XSL 是这样的:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="queryCompoundEmployeeResponse/CompoundEmployee/person/employment_information">
<xsl:copy>
<xsl:apply-templates select="job_information">
<!-- concat year, month, day -->
<xsl:sort select="concat(
substring(start_date, 1, 4),
substring(start_date, 6, 2),
substring(start_date, 9, 2)
)" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果是这样的(摘录)
如您所见,排序没问题,但来自就业信息的其他孩子已经走了。 我如何才能保留它们?我错过了什么?
<employment_information>
<job_information>
<shift_factor>0.0</shift_factor>
<shift_rate>0.0</shift_rate>
<standard_hours>0.0</standard_hours>
<start_date>2020-10-01</start_date>
<timezone>Europe/Amsterdam</timezone>
<workingDaysPerWeek>0.0</workingDaysPerWeek>
</job_information>
<job_information>
<action>CHANGE</action>
<shift_factor>0.0</shift_factor>
<shift_rate>0.0</shift_rate>
<standard_hours>38.0</standard_hours>
<start_date>2020-10-10</start_date>
<time_recording_admissibility_code>NL</time_recording_admissibility_code>
<time_recording_profile_code>NL</time_recording_profile_code>
<time_recording_variant>DURATION</time_recording_variant>
<time_type_profile_code>NL20+/CI+</time_type_profile_code>
<timezone>Europe/Amsterdam</timezone>
<workingDaysPerWeek>5.0</workingDaysPerWeek>
<workschedule_code>DUMMY</workschedule_code>
</job_information>
</employment_information>
【问题讨论】:
【参考方案1】:您需要做的是复制其他节点(<employment_information>
的子节点,但不是 <job_information>
的子节点)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="employment_information">
<xsl:copy>
<xsl:apply-templates select="node()[not(self::job_information)] | @*" />
<xsl:apply-templates select="job_information">
<!-- concat year, month, day -->
<xsl:sort select="concat(
substring(start_date, 1, 4),
substring(start_date, 6, 2),
substring(start_date, 9, 2)
)" data-type="number" order="ascending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我使用了<xsl:apply-templates select="node()[not(self::job_information)] | @*" />
,因为这会触发身份模板,最终将复制这些节点。但在这种特殊情况下,<xsl:copy-of select="node()[not(self::job_information)] | @*" />
也可以正常工作。
Michael 的评论是正确的 - 这是没有明确说明所需子订单的不幸后果。为了保持原来的元素顺序,可以更细粒度地定位内部<xsl:apply-templates>
,比如
<!-- 1. all child nodes that come before the <job_information> block -->
<xsl:apply-templates select="node()[not(self::job_information) and following-sibling::job_information]" />
<!-- 2. the <job_information> block itself -->
<xsl:apply-templates select="job_information">
<xsl:sort ... />
</xsl:apply-templates>
<!-- 3. all child nodes that come after the <job_information> block -->
<xsl:apply-templates select="node()[not(self::job_information) and preceding-sibling::job_information]" />
但是这种方法需要保证<job_information>
元素是一个块,中间没有杂散元素。最后的决定是当其他节点切换位置时是否有任何中断,或者您的用例是否足以让<job_information>
以正确的顺序出现。
【讨论】:
@Tom64 请注意,这将移动job_event_information
并将其放在所有 job_information
节点之前。如果这是可以接受的,那么这对您应该很有效。 -- 另外,你可以简单地使用<xsl:sort select="start_date"/>
而不是所有的爵士乐。
确实job_event_information由于模板的较早应用而移动了,但这不是问题。
而且我不需要那些爵士乐 :)以上是关于使用 `<xsl:apply-templates>` 排序后缺少一些子节点的主要内容,如果未能解决你的问题,请参考以下文章
何时使用 Mono<List<Object>> 以及何时使用 Flux<Object> 用于 RestController 方法
我应该使用 <colgroup> 和 <col>,如果是,为啥以及如何使用?
如何使用 Python 使用 Selenium 获取 <ul> 中的 <li> 元素列表?
<q>、<blockquote> 和 <cite> 的有效使用