我正在尝试将从数据库中读取的旅行行程输出为PDF。 Retreiving等等都很好,但我想按日期订购行程。
目前xml结构如下
<flights>
<flDate>13OCT</flDate>
<flFrom>Glasgow International </flFrom>
<flTo>Philadelphia, PA - International </flTo>
<flNumber>US769</flNumber>
<depTime>1020</depTime>
<arrTime>1300</arrTime>
</flights>
<flights>
<flDate>22OCT</flDate>
<flFrom>Philadelphia, PA - International </flFrom>
<flTo>Glasgow International </flTo>
<flNumber>US768</flNumber>
<depTime>1855</depTime>
<arrTime>1830</arrTime>
</flights>
<accommodation>
<accDate>14OCT</accDate>
<accName>Hotel Los Jameos</accName>
<duration>10</duration>
<roomType>Type B Rooms</roomType>
<boardBasis>H/B</boardBasis>
</accommodation>
目前的输出是
13OCT Glasgow to Phili
..........
22OCT Phili to Glasgow
..........
14OCT Hotel Los Jameos
..........
显然这不理想,导致混乱。理想情况下,我希望住宿(以及任何其他行程项目)的日期顺序正确。
我该怎么做?我在想它可能是对数据库或XML的改进结构。
下面的当前XSL。
<xsl:for-each select="iOverview/itinLeg">
<xsl:sort select="flights/flDate" order="descending"/>
<xsl:sort select="accommodation/accDate" order="descending"/>
<xsl:apply-templates select="flights[count(.|key('fDate', flDate)[1])=1]"/>
<xsl:apply-templates select="accommodation"/>
</xsl:for-each>
<xsl:template match="flights">
<fo:block margin-top="2mm">
<xsl:for-each select="key('fDate', flDate)">
<xsl:sort select="flDate"/>
<fo:block>
<fo:inline font-weight="bold"><xsl:value-of select="flDate"/></fo:inline>
<fo:inline padding-left="4mm"><xsl:value-of select="flFrom"/></fo:inline>
<fo:inline padding-left="1mm">to</fo:inline>
<fo:inline padding-left="2mm"><xsl:value-of select="flTo"/></fo:inline>
</fo:block>
.......
</xsl:for-each>
</fo:block>
</xsl:template>
住宿xsl真的只是不同的元素名称。
感谢您提出任何建议。
答案 0 :(得分:1)
首先,您在使用此日期格式排序时遇到问题。将其更改为2016-10-05之类的内容,然后您可以将日期排序为字符串。
您的下一个挑战是计算航班排序键的表达式与酒店的排序键不同,但您希望排序为单个序列。但这很容易克服;只需在logger:#ILogger
:
xsl:sort/@select
答案 1 :(得分:0)
您的MCVE不是那么完整,所以我添加了<xsl:key name="fDate" match="flights" use="flDate" />
来完成它。我还从XSLT中推断出了周围的标签。可以将搜索表达式合并到flDate | accDate
来对输出进行排序。为清楚起见,我省略了XSL:FO块,您可能希望将它们读入最终解决方案。
生成的XSLT-1.0样式表如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="fDate" match="flights" use="flDate" />
<xsl:template match="/">
<xsl:for-each select="iOverview/itinLeg">
<xsl:for-each select="flights | accommodation">
<xsl:sort select="flDate | accDate" order="descending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="flights[count(.|key('fDate', flDate)[1]) = 1]">
<xsl:for-each select="key('fDate', flDate)">
<xsl:value-of select="flDate"/><xsl:text> </xsl:text><xsl:value-of select="normalize-space(flFrom)"/> to <xsl:value-of select="flTo"/><xsl:value-of select="' '" />
</xsl:for-each>
</xsl:template>
<xsl:template match="flights[count(.|key('fDate', flDate)[1]) > 1]" /> <!-- filter out any dates with more than one matches -->
<xsl:template match="accommodation">
<xsl:value-of select="accDate"/><xsl:text> </xsl:text><xsl:value-of select="accName"/><xsl:value-of select="' '" />
</xsl:template>
</xsl:stylesheet>
根据输入数据,输出如下:
22OCT Philadelphia, PA - International to Glasgow International
14OCT Hotel Los Jameos
13OCT Glasgow International to Philadelphia, PA - International
如果您认为时间顺序错误,只需更换&#34;降序&#34;用&#34;升序&#34;在`&#34;。
答案 2 :(得分:0)
让我们将示例缩小到处理按给定DMMM格式按日期排序节点问题所需的最小值(至少看起来如何)。
给出以下输入:
<强> XML 强>
<itinerary>
<flight>
<flDate>25OCT</flDate>
</flight>
<flight>
<flDate>13NOV</flDate>
</flight>
<flight>
<flDate>9SEP</flDate>
</flight>
<flight>
<flDate>13OCT</flDate>
</flight>
<flight>
<flDate>28AUG</flDate>
</flight>
<flight>
<flDate>5OCT</flDate>
</flight>
</itinerary>
以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="months" select="'JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'" />
<xsl:template match="/itinerary">
<xsl:copy>
<xsl:for-each select="flight">
<xsl:sort select="string-length(substring-before($months, translate(flDate, '0123456789', '')))" data-type="text" order="ascending"/>
<xsl:sort select="translate(flDate, 'ABCDEFGJLMNOPRSTUVY', '')" data-type="number" order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将返回:
<?xml version="1.0" encoding="UTF-8"?>
<itinerary>
<flight>
<flDate>28AUG</flDate>
</flight>
<flight>
<flDate>9SEP</flDate>
</flight>
<flight>
<flDate>5OCT</flDate>
</flight>
<flight>
<flDate>13OCT</flDate>
</flight>
<flight>
<flDate>25OCT</flDate>
</flight>
<flight>
<flDate>13NOV</flDate>
</flight>
</itinerary>
注意:当您的行程跨越一年边界时,这将产生不正确的结果:明年1月的事件将在今年12月的事件之前排序。