首页 > 解决方案 > 如何第二次停止执行“何时”条件

问题描述

我的问题是:我在下面的 xml 中循环标记并进行查找并对其执行一些逻辑(在条件之后的 xsl 中),但我不想对具有相同类别的第二个覆盖范围执行逻辑 - category1 .

在循环中的第一次,我将覆盖代码作为 -GOLD 并且查找将返回值作为 -category 1 并将执行逻辑。在循环中的第二次我将得到覆盖代码作为 -SILVER 并且查找将返回值作为 -category1 (相同类别)所以我不想在条件满足时执行 xsl 之后的逻辑。

谁能建议我如何实现这一点(我想实现-对于仅存在不同的查找值(此处为 category1)执行单次逻辑。当条件将为category1执行 2 次时吹 xsl ,但我想执行逻辑for - category1一次,即使我为所有覆盖范围迭代循环。

下面是我的 XML、查找 XML 和 xsl(我添加了伪代码请忽略任何问题,我的主要重点是为我上面提出的问题找到解决方案)。

XML:

<policy>
<location>
<coverage>
<coverageCode>GOLD</<coverageCode>
</coverage>
<coverage>
<coverageCode>SILVER</<coverageCode>
</coverage>
<coverage>
<coverageCode>MONEY</<coverageCode>
</coverage>
</location>
</policy>

查找 xml:propertylookup.xml

<?xml version="1.0" encoding="UTF-8"?>
<Properties>

    
    <Property name="GOLD">category1</Property>
    <Property name="SILVER">category1</Property>
    <Property name="MONEY">category2</Property>
<property>  

下面是xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    
    xmlns:functx="http://www.functx.com"
    extension-element-prefixes="iipxsl" version="2.0">
    
    <xsl:variable name="coverageprops"
        select="document('propertylookup.xml')" />
<xsl:template match="/policy">
<policyresults>
<xsl:call-template name="policy">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</policyresults>

<xsl:template name="policy">
<xsl:for-each select="$node/location/coverage">
<xsl:variable name="covcodevalue" select="coverageCode"
<xsl:choose>
<xsl:when test="$coverageprops/Properties/Property[@name=$covcodevalue] and $coverageprops/Properties/Property[@name=$covcodevalue] ='category1'" >

---Some logic here---

</xsl:when>
</xsl:choose>

</xsl:for-each>

</xsl:template>

标签: xmlxslt

解决方案


您可以使用以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  
  <xsl:output method="xml"/>
  
  <xsl:variable name="coverageprops"  as="document-node()" select="doc('propertylookup.xml')"/>
  
  <xsl:template match="/">
    <!-- First bind the categories to the coverage in a different mode -->
    <xsl:variable name="policyWithCategories" as="element(policy)">
      <xsl:apply-templates select="policy" mode="bindCategory"/>
    </xsl:variable>
    <policyresults>
      <!-- Apply the new xml in the standerd mode  -->
      <xsl:apply-templates select="$policyWithCategories"/>
    </policyresults>
  </xsl:template>

  <!-- bind the categorie (via een attribute but it can be anything you like) in mode  mode="bindCategory" -->
  <xsl:template match="coverage" mode="bindCategory">
    <xsl:variable name="covcodevalue" select="coverageCode/text()"/>
    <xsl:copy>
      <xsl:attribute name="category" select="$coverageprops/Properties/Property[@name=$covcodevalue]/text()"/>
      <xsl:apply-templates mode="#current"/>
    </xsl:copy>
  </xsl:template>

  <!-- since there are only elements and text-nodes in your example we only need this template to copy teh rest of the xml. in this bindCategory-mode -->
  <xsl:template match="*" mode="bindCategory">
    <xsl:copy>
      <xsl:apply-templates mode="#current"/>
    </xsl:copy>
  </xsl:template>
  
  <!-- instead off for-each it is best-practise just to use the xslt-engine using apply-templates -->
  <xsl:template match="*">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- And finally do something with the coverage if it does not have a same preceding-siblinf with the attribute @category-->
  <xsl:template match="coverage">
    <xsl:variable name="category" select="@category"/>
    <xsl:if test="not(preceding-sibling::*[@category=$category])">
      <!-- Some logic here: i.e. -->
      <firstCategory>
        <xsl:copy-of select="@*,*"/>
      </firstCategory>
    </xsl:if>
  </xsl:template>
    
</xsl:stylesheet>
  

推荐阅读