0

I was asked to generate a comma separated list generated from an XML document. When the discounts only consisted of nodes grouped together under the vehicle node it worked OK (I have limited understanding of XPath). Then I was asked to add one more discount that is located in a different section of the XML. Using this approach I can't seem to get the value of the node I need. For clarification, I don't create this XML file, it is generated by a vendor system and is roughly 5K lines long. I used this post from SO as the basis for creating the list.


Desired Output (if node in loop != '0' or PaymentPlanCd != 'PaidInFull' add to the list - psuedo-code)

Multi-Car, Homeowner, Affinity, In-Agency Transfer, Advanced Purchase, Incident Free, Annual Mileage, Paid in Full Discount


I was getting an extra comma at the end so I changed to a whitespace based approach that seemed to work (Method 2). I would rather have the comma based approach (Method 1) though. Below is a sample of the XML document and the code I'm currently trying to make work. If there is an easier or more eloquent solution, I'm all ears.

Sample XML (@pval stands for "Proposal Value")

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

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

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

How would I get method 1 working in this scenario? Thanks for all the help.

Community
  • 1
  • 1
mmarceau
  • 59
  • 1
  • 9
  • I don't understand this part: "*(if node in loop != '0' or PaymentPlanCd != 'PaidInFull' add to the list)*" – michael.hor257k Sep 10 '14 at 18:10
  • That is in reference to the nodes in the for-each loop. `` Basically psuedo-code. – mmarceau Sep 10 '14 at 18:26
  • But what does it **mean**? Normally, a CSV output has a "field" for every "column" in every row. IOW,no nodes can be excluded, otherwise the following nodes will be shifted to the wrong "column". – michael.hor257k Sep 10 '14 at 18:35
  • The XML file that gets created by the system isn't a CSV file so there is nothing to do with columns. It is far more complex than the sample I included above. I apologize if I'm not explaining this correctly. – mmarceau Sep 11 '14 at 13:37
  • I am afraid I have no idea what your question is at this point. – michael.hor257k Sep 11 '14 at 14:58

1 Answers1

0

I am not sure what the difficulty here is. Could you try the following stylesheet and tell us - in simple, non-technical language - what (if anything) is missing?

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>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Each vehicle node in the larger XML file contains roughly 1100 lines, The sample I posted was for simplicity sake, the actual XML file is far from simple. That is why I had to target the discount nodes specifically. – mmarceau Sep 11 '14 at 14:41