這是一個很長很長的問題。道歉。比較兩個列表
我的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>