繁体   English   中英

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

[英]Create a concatenated, comma separated list from XML nodes at different levels in the XML tree using XPath/XSLT

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


所需的输出 (如果循环中的节点!='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>

方法二

<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起作用? 感谢您的所有帮助。

我不确定这里的困难是什么。 您能否尝试以下样式表,并以简单的非技术性语言告诉我们-缺少什么(如有)?

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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM