【问题标题】:XSLT issue compare two xpath and transform xmlXSLT 问题比较两个 xpath 并转换 xml
【发布时间】:2023-03-03 04:24:01
【问题描述】:

我需要通过比较两个不同的 xpath 来创建一个 xslt,并从 children 中获取值并转换 XML。

规则如下:

1.)I need to compare the location-number inside buildings/building/building-header/location-number with buildings/policy/coverages/coverage/location-rule/insured-objects/insured-object/insured-object-nr and for the locations not matching i need to create element Policy/PolicyConditions/Name as No coverage and map the Policy/PolicyConditions/PolicyConditionCriteria/Value as the building-number ie.,LU4-B1 in my below example.

2.)for each buildings/policy/coverages/coverage check for limit/limit-type/@code is Bla and for each location-rule/insured-objects/insured-object/insured-object-nr check for location-number inside buildings/building/building-header/location-number and get the
buildings/building/building-header/building-number create Policy/PolicyConditions/Name as EQ Blanket and map the Policy/PolicyConditions/PolicyConditionCriteria/Value as the building-number LU1-B1,LU1-B1,LU2-B2

3.)for each buildings/policy/coverages/coverage check for limit/limit-type/@code is Sub and for each location-rule/insured-objects/insured-object/insured-object-nr check for location-number inside buildings/building/building-header/location-number and get the
buildings/building/building-header/building-number create Policy/PolicyConditions/Name as EQ Sublimit and map the Policy/PolicyConditions/PolicyConditionCriteria/Value as the building-number LU2-B1,LU2-B2,LU3-B1,LU3-B2

Rule 2 and 3 are more or less the same only check that is different is with the limit/limit-type/@code.

我能够实现规则 2 和规则 3,但无法为不匹配的 xpath 编写实现规则 1 的逻辑。

我只能使用 xslt 1.0 版

输入:

<buildings>
<building>
            <building-header>
                <location-number>LU1</location-number>
                <building-number>LU1-B1</building-number>
            </building-header>
</building> 
<building>
            <building-header>
                <location-number>LU2</location-number>
                <building-number>LU2-B1</building-number>
            </building-header>
</building>
<building>
            <building-header>
                <location-number>LU2</location-number>
                <building-number>LU2-B2</building-number>
            </building-header>
</building>
<building>
            <building-header>
                <location-number>LU3</location-number>
                <building-number>LU3-B1</building-number>
            </building-header>
</building>
<building>
            <building-header>
                <location-number>LU3</location-number>
                <building-number>LU3-B2</building-number>
            </building-header>
</building>
<building>
            <building-header>
                <location-number>LU4</location-number>
                <building-number>LU4-B1</building-number>
            </building-header>
</building>     

<policy-details>
<coverages>
<coverage>
<limit>
        <limit-type code="Bla"/>
</limit>
<location-rule>
                        <insured-objects>
                            <insured-object>
                                <insured-object-nr>LU1</insured-object-nr>
                            </insured-object>
                            <insured-object>
                                <insured-object-nr>LU2</insured-object-nr>
                            </insured-object>
                        </insured-objects>
</location-rule>
</coverage>
<coverage>
<limit>
        <limit-type code="Sub"/>
</limit>
<location-rule>
                        <insured-objects>
                            <insured-object>
                                <insured-object-nr>LU2</insured-object-nr>
                            </insured-object>
                            <insured-object>
                                <insured-object-nr>LU3</insured-object-nr>
                            </insured-object>
                        </insured-objects>
</location-rule>
</coverage>
</coverages>
</policy>
</buildings>

XSLT 示例:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<policy>
<xsl:for-each select="//coverage">
<xsl:if test="limit/limit-type/@code='Bla'">
<PolicyConditions>
<Name>EQ Blanket</Name>
<xsl:for-each select="location-rule/insured-objects/insured-object">
<xsl:variable name="var_Ins_Obj">
    <xsl:value-of select="insured-object-nr"/>
</xsl:variable>
<xsl:for-each select="//building">
                                                    <xsl:variable name="var_loc_Num">
                                                        <xsl:value-of select="building-header/location-number"/>
                                                    </xsl:variable>
                                                    <xsl:if test="$var_loc_Num=$var_Ins_Obj">
                                                        <xsl:variable name="locBuild">
                                                            <xsl:value-of select="building-header/building-number"/>
                                                        </xsl:variable>
                                                        <PolicyConditionCriteria>
                                                            <Field>LOCNAME</Field>
                                                            <Value>
                                                                <xsl:value-of select="$locBuild"/>
                                                            </Value>
                                                        </PolicyConditionCriteria>
                                                    </xsl:if>
                                                </xsl:for-each>
</xsl:for-each>
</PolicyConditions>
</xsl:if>
<xsl:if test="limit/limit-type/@code='Sub'">
<PolicyConditions>
<Name>EQ Sublimit</Name>
<xsl:for-each select="location-rule/insured-objects/insured-object">
<xsl:variable name="var_Ins_Obj">
    <xsl:value-of select="insured-object-nr"/>
</xsl:variable>
<xsl:for-each select="//building">
                                                    <xsl:variable name="var_loc_Num">
                                                        <xsl:value-of select="building-header/location-number"/>
                                                    </xsl:variable>
                                                    <xsl:if test="$var_loc_Num=$var_Ins_Obj">
                                                        <xsl:variable name="locBuild">
                                                            <xsl:value-of select="building-header/building-number"/>
                                                        </xsl:variable>
                                                        <PolicyConditionCriteria>
                                                            <Field>LOCNAME</Field>
                                                            <Value>
                                                                <xsl:value-of select="$locBuild"/>
                                                            </Value>
                                                        </PolicyConditionCriteria>
                                                    </xsl:if>
                                                </xsl:for-each>
</xsl:for-each>
</PolicyConditions>
</xsl:if>
</xsl:for-each>
</policy>
</xsl:template>
</xsl:stylesheet>

实际输出:

<policy>
   <PolicyConditions>
      <Name>EQ Blanket</Name>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU1-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B2</Value>
      </PolicyConditionCriteria>
   </PolicyConditions>
   <PolicyConditions>
      <Name>EQ Sublimit</Name>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B2</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU3-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU3-B2</Value>
      </PolicyConditionCriteria>
   </PolicyConditions>

预期输出:

<Policy>
   <PolicyConditions>
      <Name>No Coverage</Name>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU4-B1</Value>
      </PolicyConditionCriteria>
   </PolicyConditions>
   <PolicyConditions>
      <Name>EQ Blanket</Name>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU1-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B2</Value>
      </PolicyConditionCriteria>
   </PolicyConditions>
   <PolicyConditions>
      <Name>EQ Sublimit</Name>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU2-B2</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU3-B1</Value>
      </PolicyConditionCriteria>
      <PolicyConditionCriteria>
         <Field>LOCNAME</Field>
         <Value>LU3-B2</Value>
      </PolicyConditionCriteria>
   </PolicyConditions>
</Policy>

【问题讨论】:

    标签: xslt xslt-1.0


    【解决方案1】:

    这是一种解决方案:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
        <xsl:variable name="noCoverage">
            <xsl:for-each select="//building/building-header/location-number">
                <xsl:variable name="locationNumber" select="text()"/>
                <xsl:if test="boolean(//coverage/location-rule/insured-objects/insured-object/insured-object-nr[text()=$locationNumber]) = false">
                    <xsl:value-of select="'true'"/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
    
        <xsl:template match="/">
            <policy>
                <xsl:if test="contains($noCoverage, 'true')">
                    <PolicyConditions>
                        <Name>No Coverage</Name>
                        <xsl:for-each select="//building/building-header/location-number">
                            <xsl:variable name="locationNr" select="text()"/>
                            <xsl:if test="boolean(//coverage/location-rule/insured-objects/insured-object/insured-object-nr[text()=$locationNr]) = false">
                                <PolicyConditionCriteria>
                                    <Field>LOCNAME</Field>
                                    <Value>
                                        <xsl:value-of select="../building-number"/>
                                    </Value>
                                </PolicyConditionCriteria>
                            </xsl:if>
                        </xsl:for-each>     
                    </PolicyConditions>
                </xsl:if>
    
                <xsl:for-each select="//coverage">
                    <xsl:if test="limit/limit-type/@code='Bla'">
                        <PolicyConditions>
                            <Name>EQ Blanket</Name>
                            <xsl:for-each select="location-rule/insured-objects/insured-object">
                                <xsl:variable name="var_Ins_Obj">
                                    <xsl:value-of select="insured-object-nr"/>
                                </xsl:variable>
                                <xsl:for-each select="//building">
                                    <xsl:variable name="var_loc_Num">
                                        <xsl:value-of select="building-header/location-number"/>
                                    </xsl:variable>
                                    <xsl:if test="$var_loc_Num=$var_Ins_Obj">
                                        <xsl:variable name="locBuild">
                                            <xsl:value-of select="building-header/building-number"/>
                                        </xsl:variable>
                                        <PolicyConditionCriteria>
                                            <Field>LOCNAME</Field>
                                            <Value>
                                                <xsl:value-of select="$locBuild"/>
                                            </Value>
                                        </PolicyConditionCriteria>
                                    </xsl:if>
                                </xsl:for-each>
                            </xsl:for-each>
                        </PolicyConditions>
                    </xsl:if>
                    <xsl:if test="limit/limit-type/@code='Sub'">
                        <PolicyConditions>
                            <Name>EQ Sublimit</Name>
                            <xsl:for-each select="location-rule/insured-objects/insured-object">
                                <xsl:variable name="var_Ins_Obj">
                                    <xsl:value-of select="insured-object-nr"/>
                                </xsl:variable>
                                <xsl:for-each select="//building">
                                    <xsl:variable name="var_loc_Num">
                                        <xsl:value-of select="building-header/location-number"/>
                                    </xsl:variable>
                                    <xsl:if test="$var_loc_Num=$var_Ins_Obj">
                                        <xsl:variable name="locBuild">
                                            <xsl:value-of select="building-header/building-number"/>
                                        </xsl:variable>
                                        <PolicyConditionCriteria>
                                            <Field>LOCNAME</Field>
                                            <Value>
                                                <xsl:value-of select="$locBuild"/>
                                            </Value>
                                        </PolicyConditionCriteria>
                                    </xsl:if>
                                </xsl:for-each>
                            </xsl:for-each>
                        </PolicyConditions>
                    </xsl:if>
                </xsl:for-each>
    
            </policy>
        </xsl:template>
    </xsl:stylesheet>
    

    基本上,我添加了一个变量,用于检查是否有没有对应的被保险人对象编号的位置编号。如果有,我将字符串“true”添加到变量的值中。

    然后,在模板中检查变量名,并再次检查当前位置编号是否没有对应的被保险人编号。

    【讨论】:

    • 感谢它提供了很大帮助的解决方案。
    • 亲爱的 Maria,我们发现这种方法有一个局限性,该方法假设元素保值对象 nr 和位置编号位于一个唯一的 XPATH 中。如果 xml 发生变化,并且将来有新的同名元素使用不同的 xpath,我们不会注意到这一点并遇到错误。有什么替代方法吗?
    • 是的,您可以指定 xpath,就像您在 xslt 的其他部分中所做的那样。我将编辑我的答案。
    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    相关资源
    最近更新 更多