迭代后的 XSLT 3.0 断言和异常抛出

XSLT 3.0 assertion and exception throwing after iteration

我有包含依赖组件的 XSLT 模块:迭代、验证和……

Input example port1.xml

<valuationDocument>
  <valuationSet id="val1">
    <assetValuation>
      <objectReference href="tid-1" />
      <quote>
        <value>1000000</value>
        <sensitivitySet>
          <sensitivity name="SEP21">0.707</sensitivity>
          <sensitivity name="2Y">1.82</sensitivity>
          <sensitivity name="3Y">2.73</sensitivity>
          <sensitivity name="4Y">3.68</sensitivity>
          <sensitivity name="5Y">4.51</sensitivity>
          <sensitivity name="7Y">3.64</sensitivity>
          <sensitivity name="10Y">9.06</sensitivity>
          <sensitivity name="MAR21">0.315</sensitivity>
          <sensitivity name="15Y">13.59</sensitivity>
        </sensitivitySet>
      </quote>
    </assetValuation>
    <assetValuation>
      <objectReference href="tid-2" />
      <quote>
        <value>1100000</value>
        <sensitivitySet>
          <sensitivity name="SEP21">0.947</sensitivity>
          <sensitivity name="MAR21">0.502</sensitivity>
          <sensitivity name="2Y">1.91</sensitivity>
          <sensitivity name="3Y">2.84</sensitivity>
          <sensitivity name="4Y">3.72</sensitivity>
          <sensitivity name="5Y">4.63</sensitivity>
          <sensitivity name="7Y">3.71</sensitivity>
          <sensitivity name="10Y">9.15</sensitivity>
          <sensitivity name="15Y">13.64</sensitivity>
        </sensitivitySet>
      </quote>
    </assetValuation>
  </valuationSet>
</valuationDocument>

I am quasi-satisfied with the iteration component (incapacitating the streaming…). The iteration result is below:

<valuationDocument>
   <valuationSet id="val1">
      <assetValuation>
         <objectReference href="tid-1"/>
         <quote>
            <value>1000000</value>
            <BasisPointValue>
               <shiftUp units="100bp" sensitivityName="SEP21" sensitivity="0.707">992,930.00</shiftUp>
               <shiftDown units="100bp" sensitivityName="SEP21" sensitivity="0.707">1,007,070.00</shiftDown>
==========================================================================================
               <shiftUp units="100bp" sensitivityName="15Y" sensitivity="13.59">864,100.00</shiftUp>
               <shiftDown units="100bp" sensitivityName="15Y" sensitivity="13.59">1,135,900.00</shiftDown>
            </BasisPointValue>
            <sensitivitySet>
               <sensitivity name="SEP21">0.707</sensitivity>
               <sensitivity name="2Y">1.82</sensitivity>
               <sensitivity name="3Y">2.73</sensitivity>
               <sensitivity name="4Y">3.68</sensitivity>
               <sensitivity name="5Y">4.51</sensitivity>
               <sensitivity name="7Y">3.64</sensitivity>
               <sensitivity name="10Y">9.06</sensitivity>
               <sensitivity name="MAR21">0.315</sensitivity>
               <sensitivity name="15Y">13.59</sensitivity>
            </sensitivitySet>
         </quote>
      </assetValuation>
      <assetValuation>
        <objectReference href="tid-2" />
           <quote>
              <value>1100000</value>
            <BasisPointValue>
               <shiftUp units="100bp" sensitivityName="SEP21" sensitivity="0.947">1,089,583.00</shiftUp>
               <shiftDown units="100bp" sensitivityName="SEP21" sensitivity="0.947">1,110,417.00</shiftDown>
==========================================================================================
               <shiftUp units="100bp" sensitivityName="15Y" sensitivity="13.64">949,960.00</shiftUp>
               <shiftDown units="100bp" sensitivityName="15Y" sensitivity="13.64">1,250,040.00</shiftDown>
            </BasisPointValue>
            <sensitivitySet>
               <sensitivity name="SEP21">0.947</sensitivity>
               <sensitivity name="MAR21">0.502</sensitivity>
               <sensitivity name="2Y">1.91</sensitivity>
               <sensitivity name="3Y">2.84</sensitivity>
               <sensitivity name="4Y">3.72</sensitivity>
               <sensitivity name="5Y">4.63</sensitivity>
               <sensitivity name="7Y">3.71</sensitivity>
               <sensitivity name="10Y">9.15</sensitivity>
               <sensitivity name="15Y">13.64</sensitivity>
            </sensitivitySet>
         </quote>
      </assetValuation>
   </valuationSet>
</valuationDocument>

I would like to validate the iteration result as soon as it completes. Should any of the validation fail, the exception is reported and the program is terminated. However, the validation ISN'T played out after the iteration. (The actual validation is to raise exception through xsl:try|catch and terminate if any of the assertion fails)

The validation logic is to compare three metrics of the sensitivitySet/sensitivity with those of iterated & transformed BasisPointValue/shiftUp|shiftDown/@sensitivity (NOTE: xsl:text is to simulate exception throwing, apparently, the XSLT editor can’t emit the message)

    <xsl:variable name="MinE">
        <!-- <xsl:message terminate="yes">Fatal Error: Minimum NPV and BPV sensitivity is different</xsl:message>-->
        <xsl:text>&#x9;&#xA;</xsl:text>
        <xsl:text>Retro: Min NPV and BPV sensitivity</xsl:text>
        <xsl:text>&#x9;&#xA;</xsl:text>
    </xsl:variable> 
    <xsl:variable name="MaxE">
        <!--<xsl:message terminate="yes">Fatal Error: Maximum NPV and BPV sensitivity is different</xsl:message>-->
        <xsl:text>&#x9;&#xA;</xsl:text>
        <xsl:text>Retro: Max NPV and BPV sensitivity</xsl:text>
        <xsl:text>&#x9;&#xA;</xsl:text>
    </xsl:variable> 
    <xsl:variable name="AvgDownE">
        <!--<xsl:message terminate="yes">Fatal Error: Average NPV and BPV ShiftDown sensitivity is different</xsl:message>-->
        <xsl:text>&#x9;&#xA;</xsl:text>
        <xsl:text>Retro: Average NPV and BPV ShiftDown</xsl:text>
        <xsl:text>&#x9;&#xA;</xsl:text>
    </xsl:variable>
    
    <xsl:template match="/">
        <xsl:source-document href="port1.xml">
             <xsl:apply-templates select="valuationDocument" mode="val"/>
        </xsl:source-document>
    </xsl:template>

    <xsl:template match="sensitivitySet" mode="val">

<!--  ITERATION -->     
    ==========================================
        <!--        <xsl:apply-imports/>-->
         <xsl:copy-of select="."/>
        <xsl:apply-templates select="parent::quote" mode="validation"/>
    </xsl:template>
  
<!--  VALIDATION -->
    <xsl:template match="quote" mode="validation" expand-text="yes">
        <Assertion>
             <xsl:variable name="m" as="map(*)">
                <xsl:map>
                   <xsl:map-entry key="'min-npv'" select="min(outermost(descendant::sensitivity)/number())"/>
                   <xsl:map-entry key="'max-npv'" select="max(outermost(descendant::sensitivity)/number())"/>
                   <xsl:map-entry key="'min-bpv'" select="min(outermost(descendant::BasisPointValue//@sensitivity)/number())"/>
                   <xsl:map-entry key="'max-bpv'" select="max(outermost(descendant::BasisPointValue//@sensitivity)/number())"/>
                   <xsl:map-entry key="'avg-npv'" select="avg(outermost(descendant::sensitivity)/number())"/>
                   <xsl:map-entry key="'avg-bpv-down'" select="avg(outermost(descendant::BasisPointValue/shiftDown/@sensitivity)/number())"/>
                 </xsl:map>
              </xsl:variable>
                    <xsl:choose>
                        <xsl:when test="deep-equal($m('min-npv'), $m('min-bpv'))">
                            <xsl:value-of select="$MinE"/>
                        </xsl:when>
                        <xsl:when test="deep-equal($m('max-npv'), $m('max-bpv'))">
                            <xsl:value-of select="$MaxE"/>
                        </xsl:when>
                        <xsl:when test="deep-equal($m('avg-npv'), $m('avg-bpv-down'))">
                            <xsl:value-of select="$AvgDownE"/>
                        </xsl:when>
                        <xsl:otherwise><xsl:value-of select="'Validation Succeeds!'"/></xsl:otherwise>
                    </xsl:choose>
        </Assertion> 
    </xsl:template>

What is the XSLT3.0 solution of validation after the iteration?

如果我没看错的话,这是一个标准的多相变换。您可以使用两个单独的样式表,使用一些外部 API(例如 shell 脚本、Ant/gradle、XProc、Java 应用程序)链接在一起,或者您可以将两个阶段都放在使用 logic

的相同样式表
<xsl:variable name="temp">
  <xsl:apply-templates select="/" mode="phase-1"/>
</xsl:variable>
<xsl:apply-templates select="$temp" mode="phase-2"/>