2014-09-10 46 views
0

我被要求生成從XML文檔生成的逗號分隔列表。當折扣只包含在車輛節點下組合在一起的節點時,它工作正常(我對XPath的理解有限)。然後我被要求增加一個位於XML不同部分的折扣。使用這種方法我似乎無法獲得我需要的節點的價值。爲了澄清,我不創建這個XML文件,它由供應商系統生成,大約5K行。我使用SO的post作爲創建列表的基礎。使用XPath/XSLT從XML樹中不同級別的XML節點創建連接逗號分隔列表


所需的輸出(如果在環路節點= '0' 或PaymentPlanCd = 'PaidInFull' 添加到列表中! - 僞代碼)

多轎廂,房主,親和,在-Agency轉移,需提前預定,無事故,年行駛里程,在全額貼息


我得到一個最後的額外的逗號付費,所以我改成一個空格基礎的方法,似乎工作(方法2)。儘管如此,我寧願使用基於逗號的方法(方法1)。以下是XML文檔和我目前正在努力工作的代碼示例。如果有一個更容易或更有說服力的解決方案,我就會全神貫注。

示例XML(@pval代表 「建議值」)

<dataStore> 
    <session> 
    <data> 
     <policy> 
      <PersPolicy> 
       <PaymentOption> 
        <PaymentPlanCd>PaidInFull</PaymentPlanCd> 
       </PaymentOption> 
      </PersPolicy> 
      <line> 
       <vehicle id="1"> 
        <DiscountPremMultiCar pval="Multi-Car">80</DiscountPremMultiCar> 
        <DiscountPremHomeowners pval="Homeowner">63</DiscountPremHomeowners> 
        <DiscountPremAffinity pval="Affinity">0</DiscountPremAffinity> 
        <DiscountPremInAgencyTransfer pval="In-Agency Transfer">57</DiscountPremInAgencyTransfer> 
        <DiscountPremAdvPurchase pval="Advanced Purchase">15</DiscountPremAdvPurchase> 
        <DiscountPremIncidentFree pval="Incident Free">30</DiscountPremIncidentFree> 
        <DiscountPremAnnualMileage pval="Annual Mileage">0</DiscountPremAnnualMileage> 
       </vehicle>     
       <vehicle id="2"> 
        <DiscountPremMultiCar pval="Multi-Car">80</DiscountPremMultiCar> 
        <DiscountPremHomeowners pval="Homeowner">63</DiscountPremHomeowners> 
        <DiscountPremAffinity pval="Affinity">0</DiscountPremAffinity> 
        <DiscountPremInAgencyTransfer pval="In-Agency Transfer">57</DiscountPremInAgencyTransfer> 
        <DiscountPremAdvPurchase pval="Advanced Purchase">15</DiscountPremAdvPurchase> 
        <DiscountPremIncidentFree pval="Incident Free">30</DiscountPremIncidentFree> 
        <DiscountPremAnnualMileage pval="Annual Mileage">0</DiscountPremAnnualMileage> 
       </vehicle> 
      </line> 
     </policy> 
    </data> 
    </session> 
</dataStore> 

XSLT/XPath的

<xsl:for-each select="//session/data/policy/line/vehicle"> 
    <xsl:call-template name="VehicleDiscounts" /> 
</xsl:for-each> 

方法1

<xsl:template name="VehicleDiscounts"> 
    <xsl:for-each select="DiscountPremAdvPurchase/text() | DiscountPremAffinity/text() | DiscountPremAnnualMileage/text() | DiscountPremEmployee/text() | DiscountPremHomeowners/text() | DiscountPremInAgencyTransfer/text() | DiscountPremMultiCar/text() | DiscountPremMultiPolicy/text() | DiscountPremIncidentFree/text() | ../../../PersPolicy/PaymentOptions/PaymentPlanCd/text()"> 
    <xsl:if test="../. != '0'"> 
     <xsl:value-of select="../@pval"/> 
     <xsl:if test="not(position() = last())">, </xsl:if> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

方法2

<xsl:template name="VehicleDiscounts"> 
    <xsl:for-each select="DiscountPremAdvPurchase/text() | DiscountPremAffinity/text() | DiscountPremAnnualMileage/text() | DiscountPremEmployee/text() | DiscountPremHomeowners/text() | DiscountPremInAgencyTransfer/text() | DiscountPremMultiCar/text() | DiscountPremMultiPolicy/text() | DiscountPremIncidentFree/text() | ../../../PersPolicy/PaymentOptions/PaymentPlanCd/text()"> 
    <xsl:choose> 
     <xsl:when test="name(../.) = 'DiscountPremAdvPurchase'"> 
      <xsl:if test="../. != '0'"> 
      Advance Purchase 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremAffinity'"> 
      <xsl:if test="../. != '0'"> 
      Affinity 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremEmployee'"> 
      <xsl:if test="../. != '0'"> 
      Group 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremHomeowners'"> 
      <xsl:if test="../. != '0'"> 
      Homeowners 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremInAgencyTransfer'"> 
      <xsl:if test="../. != '0'"> 
      In-Agency Transfer 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremMultiCar'"> 
      <xsl:if test="../. != '0'"> 
      Multi-Car 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremMultiPolicy'"> 
      <xsl:if test="../. != '0'"> 
      Multi-Policy 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremIncidentFree'"> 
      <xsl:if test="../. != '0'"> 
      Incident-Free 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
     <xsl:when test="name(../.) = 'DiscountPremAnnualMileage'"> 
      <xsl:if test="../. != '0'"> 
      Annual Mileage 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
<!-- This is what I have no clue about --> 
     <xsl:when test="name(../.) = 'PaymentPlanCd'"> 
      Paid In Full Discount 
      <xsl:if test="../. != '0'"> 
      Paid In Full Discount 
      <xsl:if test="not(position() = last())">&#160;&#160;&#160;&#160;</xsl:if> 
      </xsl:if> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:for-each> 
</xsl:template> 

我將如何獲得方法1在這種情況下工作?感謝所有的幫助。

+0

我不明白這個部分: 「*(如果在環路節點= '0' 或PaymentPlanCd = 'PaidInFull' 添加到列表中!)*」 – 2014-09-10 18:10:04

+0

那是參考for-each循環中的節點。 ()| DiscountPremEmployee/text()| DiscountPremEmployee/text()| DiscountPremInAgencyTransfer/text()| DiscountPremMultiCar/text()|折扣優先購買折扣/ text()|折扣優惠折扣/ )| DiscountPremMultiPolicy/text()| DiscountPremIncidentFree/text()| ../../../ PersPolicy/PaymentOptions/PaymentPlanCd/text()「>'基本上僞代碼。 – mmarceau 2014-09-10 18:26:18

+0

但它是什麼意思**?通常,CSV輸出在每行中的每個「列」都有一個「字段」。 IOW,不能排除任何節點,否則下列節點將被移動到錯誤的「列」。 – 2014-09-10 18:35:25

回答

0

我不確定這裏的困難是什麼。你可以試試下面的樣式表,並告訴我們 - 用簡單的非技術語言 - 缺少什麼(如果有的話)?

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" encoding="UTF-8"/> 

<xsl:template match="/"> 
    <xsl:text>Multi-Car,Homeowner,Affinity,In-Agency Transfer,Advanced Purchase,Incident Free,Annual Mileage,Paid in Full Discount&#10;</xsl:text> 
    <xsl:for-each select="dataStore/session/data/policy/line/vehicle"> 
     <xsl:for-each select="*"> 
      <xsl:value-of select="."/> 
      <xsl:text>,</xsl:text> 
     </xsl:for-each> 
     <xsl:value-of select="../../PersPolicy/PaymentOption/PaymentPlanCd"/> 
     <xsl:if test="not(position()=last())"> 
      <xsl:text>&#10;</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 
+0

較大的XML文件中的每個車輛節點都包含大約1100行。我發佈的示例只是爲了簡單起見,實際的XML文件並不簡單。這就是爲什麼我必須專門針對折扣節點。 – mmarceau 2014-09-11 14:41:27