这是一个很长很长的问题。道歉。比较两个列表
我的XSLT并不算太糟,正如您从我的声誉中看到的那样。我一整天都在努力解决一个编码问题,并最终提出了一个解决方案,但我不喜欢它。
在我看来,我已经设法使用函数式语言编写过程式解决方案,并且我希望更多XSLT精神的更优雅,更清洁的解决方案。
我正在做两个拥有非常类似数据的计算机系统之间的数据和解练习。
有问题的数据是公共交通路线,每条路线由点列表组成,例如,
<Routes>
<Route Id="1">
<Point Id="1"/>
<Point Id="2"/>
<Point Id="3"/>
<Point Id="4"/>
<Point Id="5"/>
</Route>
</Routes>
没有一个Id很简单,当然在递增整数。
对于“商业原因”这个路线可能会在其他系统出现
<Routes>
<Route Id="1">
<Point Id="1"/>
<Point Id="2"/>
</Route>
<Route Id="1A">
<Point Id="3"/>
<Point Id="4"/>
<Point Id="5"/>
</Route>
</Routes>
我们可以假设点号的系统往往不够之间的匹配现在
,我有一个比较路由代码1在一个系统和路由与1中的其他系统启动并可以产生类似:
<Routes>
<Route>
<Point Id="1" In="Y"/>
<Point Id="2" In="Y"/>
<Point Id="3" In="N"/>
<Point Id="4" In="N"/>
<Point Id="5" In="Y"/>
<Point Id="6" In="Y"/>
<Point Id="7" In="N"/>
<Point Id="8" In="N"/>
<Point Id="9" In="N"/>
</Route>
</Routes>
在哪里=“Y”表示一点也是SYSTE m B为此路线
这种输出对企业来说有点难以理解。他们可以处理以下更容易
<Routes>
<Route>
<Route>
<Group startPoint="1" endPoint="2" In="Y"/>
<Group startPoint="3" endPoint="4" In="N"/>
<Group startPoint="5" endPoint="6 "In="Y"/>
<Group startPoint="7" endPoint="9" In="Y"/>
</Route>
</Route>
</Routes>
很明显,我并没有真正向他们展示任何这样的事情。我向他们展示了带有文字描述的Excel工作表,但我希望减少列表中不会将状态更改为开始和结束部分的点数,因为这在商业术语中更容易理解。
换句话说,他们希望看到这条路线与其他路线的前半部分相同,然后跳过一堆点然后再次匹配。
所以....
如何减少说我们这里开始到这里说Y Y的序列和N元素,元素那么我们该N从这里到这里,然后N代表过去的几年。希望这是有道理
我的测试数据:
<Routes>
<Route>
<Point Id="1" In="Y"/>
<Point Id="2" In="Y"/>
<Point Id="3" In="N"/>
<Point Id="4" In="N"/>
<Point Id="5" In="Y"/>
<Point Id="6" In="Y"/>
<Point Id="7" In="N"/>
<Point Id="8" In="N"/>
<Point Id="9" In="N"/>
</Route>
</Routes>
我的解决办法:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/">
<Routes>
<xsl:apply-templates select="/Routes"/>
</Routes>
</xsl:template>
<xsl:template match="/Routes">
<Route>
<xsl:apply-templates select="Route"/>
</Route>
</xsl:template>
<xsl:template match="/Routes/Route">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="." mode="Pointy">
<xsl:with-param name="posn" select="1" as="xs:integer"/>
<xsl:with-param name="startPosn" select="1" as="xs:integer"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="/Routes/Route" mode="Pointy">
<xsl:param name="posn" as="xs:integer"/>
<xsl:param name="startPosn" as="xs:integer"/>
<xsl:variable name="groupType" select="Point[position()=$startPosn]/@In"/>
<xsl:if test="$posn!=1 and $groupType != Point[$posn]/@In">
<Group>
<xsl:attribute name="startPoint" select="Point[$startPosn]/@Id"/>
<xsl:attribute name="endPoint" select="Point[$posn - 1]/@Id"/>
</Group>
</xsl:if>
<xsl:if test="$posn = count(Point)">
<Group>
<xsl:attribute name="startPoint" select="Point[$startPosn]/@Id"/>
<xsl:attribute name="endPoint" select="Point[$posn]/@Id"/>
</Group>
</xsl:if>
<xsl:if test="$groupType = Point[$posn]/@In and $posn != count(Point)">
<xsl:apply-templates select="." mode="Pointy">
<xsl:with-param name="posn" select="$posn + 1" as="xs:integer"/>
<xsl:with-param name="startPosn" select="$startPosn" as="xs:integer"/>
</xsl:apply-templates>
</xsl:if>
<xsl:if test="$groupType != Point[$posn]/@In and $posn != count(Point)">
<xsl:apply-templates select="." mode="Pointy">
<xsl:with-param name="posn" select="$posn + 1" as="xs:integer"/>
<xsl:with-param name="startPosn" select="$posn" as="xs:integer"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>