使用XPath / XSLT从XML树中不同级别的XML节点创建一个以逗号分隔的连续列表

时间:2014-09-10 17:46:24

标签: xml xslt xpath

我被要求生成一个从XML文档生成的逗号分隔列表。当折扣仅由在车辆节点下组合在一起的节点组成时,它工作正常(我对XPath的理解有限)。然后我被要求再添加一个位于XML的不同部分的折扣。使用这种方法,我似乎无法获得我需要的节点的价值。为了澄清,我没有创建这个XML文件,它是由供应商系统生成的,大约是5K行。我使用SO中的post作为创建列表的基础。


所需输出(如果节点在循环中!=' 0'或者PaymentPlanCd!=' PaidInFull'添加到列表 - 伪代码)

多辆车,房主,亲和力,机构内转移,高级购买,无事故,年度里程,全额付费


我最后得到了一个额外的逗号,所以我改为基于空格的方法似乎有效(方法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在这种情况下工作?感谢您的帮助。

1 个答案:

答案 0 :(得分: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>