2014-05-17 181 views
2

這是一個很長很長的問題。道歉。比較兩個列表

我的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> 

回答

2

提供的格式

<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> 

可以使用group-adjacent

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output indent="yes"/> 

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* , node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Route"> 
    <xsl:copy> 
    <xsl:for-each-group select="Point" group-adjacent="@In"> 
     <Group startPoint="{@Id}" endPoint="{current-group()[last()]/@Id}" In="{@In}"/> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

得到

<Routes> 
    <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="N"/> 
    </Route> 
</Routes>