xml - 有没有办法编写 XSLT 转换以通过 emp、shift & swipeIn 和 Swipe Out 仅获取一条记录
问题描述
我需要为 Swipe punches 项目编写一个 XSLT 转换。目的是让员工、班次和日期只记录一条进出时间。
下面是我的 XML。我想编写 XSLT 以在一天内通过 Emp、Shift 和 Day 仅获得一次 Swipe In(应该是第一次 swipeIn)和一次 Swipe out(应该是最后一次 swipe Out)。
但是对于轮班:1C 更改刷卡日期,因为它是夜班。(夜班从下午 5 点(今天)开始到凌晨 4 点(明天)
我不确定这是否可能。
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Employees>
<Date>2019-12-16</Date>
<Time>08:53:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>10:53:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>11:10:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>12:53:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>14:00:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>18:00:54</Time>
<Empid>100</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1A</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>17:30:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>19:00:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>20:10:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-16</Date>
<Time>23:53:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-17</Date>
<Time>01:30:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-17</Date>
<Time>03:00:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
</Employees>
<Employees>
<Date>2019-12-17</Date>
<Time>03:30:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 2</Gate>
<InOut>In</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
<Employees>
<Date>2019-12-17</Date>
<Time>04:00:54</Time>
<Empid>101</Empid>
<Gate>B-1a Main Door 3</Gate>
<InOut>Out</InOut>
<Remark>Successful</Remark>
<Shift>1C</Shift>
</Employees>
</Data>
输出应该是这样的:
解决方案
主要方法是对三个关键值进行简单的复合分组,只有夜班会使事情复杂化,因为您必须对两个不同的日期进行分组,并且还必须更改表达式以查找时间:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="Data">
<table>
<thead>
<tr>
<th>Date</th>
<th>In-Time</th>
<th>Out-Time</th>
<th>EmpId</th>
<th>Shift</th>
</tr>
</thead>
<xsl:for-each-group select="Employees" composite="yes"
group-by="Empid,
if (Shift != '1C')
then
xs:date(Date)
else if (xs:time(Time) lt xs:time('08:00:00'))
then
xs:date(Date) - xs:dayTimeDuration('P1D')
else
xs:date(Date),
Shift">
<tbody>
<tr>
<td>{current-grouping-key()[2]}</td>
<td>{if (Shift != '1C')
then min(current-group()[InOut = 'In']/xs:time(Time))
else
min(current-group()[xs:date(Date) = current-grouping-key()[2]][InOut = 'In']/xs:time(Time))
}</td>
<td>{if (Shift != '1C')
then
max(current-group()[InOut = 'Out']/xs:time(Time))
else
max(current-group()[xs:date(Date) > current-grouping-key()[2]][InOut = 'Out']/xs:time(Time))}</td>
<td>{current-grouping-key()[1]}</td>
<td>{current-grouping-key()[3]}</td>
</tr>
</tbody>
</xsl:for-each-group>
</table>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bFWRAp4
这是假设夜班总是在第二天结束,如果有人因病在午夜前辍学,我不确定这是否现实。
我没有尝试格式化日期或时间,使用format-date
XSLT/XPath 提供的各种时间函数。
推荐阅读
- amazon-cloudsearch - 或使用 CloudSearch 的结构化查询解析器搜索相同的字段
- laravel - DOMPDF - 下载选定日期的报告
- mongodb - MongoDB:如果元素不存在,则通过向其添加元素来更新文档中的列表
- lua - 为什么这个输出“nan”(lua)
- reactjs - 如何将函数设置为在另一个函数之后呈现?
- javascript - 将节点js的缓冲区转换为图像并显示在网站上
- c++ - 为什么在 C++ 中调用此构造函数时会出现未定义的引用错误?
- json - 在 sqlite 中,如何将逗号分隔的键值对拆分为列?
- c# - DryWetMIDI 通过释放键盘键接收 NoteOn
- c++ - 在类中产生线程