在XSLT 1.0 for-each循环中,如何在测试条件之后比较元素与先前元素的位置?

时间:2018-07-31 09:54:49

标签: xml xslt xslt-1.0

我遍历某些元素(生成),然后测试它们的索引是否与其他节点匹配以确定元素的类型。我想显示与元素类型相关的标题(如果存在),但仅显示一次。

这是我的问题的一个示例:

XML:

<element_collection>    
   <element>
      <index>1</index>
   </element>
   <element>
      <index>2</index>
   </element>
   <element>
      <index>3</index>
   </element>
   <element>
      <index>4</index>
   </element>
</element_collection>

<element_link_type_1_collection>
   <element_link_type_1>
      <element_index>2</element_index>
   </element_link_type_1>
   <element_link_type_1>
      <element_index>3</element_index>
   </element_link_type_1>
   <element_link_type_1>
      <element_index>4</element_index>
   </element_link_type_1>
</element_link_type_1_collection>

<element_link_type_2_collection>
   <element_link_type_2>
      <element_index>1</element_index>
   </element_link_type_2>
<element_link_type_1>
      <element_index>4</element_index>
   </element_link_type_1>
</element_link_type_2_collection>

XSL for-each循环:

<xsl:for-each select="element_collection/element">
    <xsl:variable name="id_element" select="Index"/>

    <xsl:choose>
    <!-- condition for type 1 only -->
        <xsl:when test="element_link_type_1_collection/element_link_type_1/element_index = $id_element 
    and not(element_link_type_2_collection/element_link_type_2/element_index = $id_element)">

    <!-- treatment -->
        </xsl:when>
    </xsl:choose>
</xsl:for-each>

通过这个循环,您会发现我正在寻找所有元素,并检查它们的索引是否存在于element_link_type集合中,如果它们仅存在于collection_type_1中,则这些元素属于type 1 ,如果它们同时存在于type_1type_2中,则它们都是两种类型。

我的问题是,我只想显示元素类别的标题,但前提是该类型的元素存在。在我的示例中,我想返回如下内容:

  

类型1:索引-2,3

     

类型2:索引-1

     

类型1和2:索引-4

为此,我想找到第一个元素的位置以符合我的条件,但是我似乎找不到解决该问题的方法。

1 个答案:

答案 0 :(得分:1)

首先,定义一些键来查找收集项可能很容易

<xsl:key name="type1" match="element_link_type_1" use="element_index" />
<xsl:key name="type2" match="element_link_type_2" use="element_index" />

但是,解决问题的一种方法是,不仅要遍历元素一次并确定其类型,还应尝试分别为每种类型选择相关项。例如,要获取“类型1”元素,请执行此操作...

<xsl:apply-templates select="element_collection/element[key('type1', index) and not(key('type2', index))]" />

这确实有一点缺点,尽管您需要对每个元素进行三遍检查:

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" />

  <xsl:key name="type1" match="element_link_type_1" use="element_index" />
  <xsl:key name="type2" match="element_link_type_2" use="element_index" />

  <xsl:template match="elements">
      <xsl:text>Type 1: </xsl:text>
      <xsl:apply-templates select="element_collection/element[key('type1', index) and not(key('type2', index))]" />
      <xsl:text>&#10;</xsl:text>

      <xsl:text>Type 2: </xsl:text>
      <xsl:apply-templates select="element_collection/element[key('type2', index) and not(key('type1', index))]" />
      <xsl:text>&#10;</xsl:text>

      <xsl:text>Type 1 and 2: </xsl:text>
      <xsl:apply-templates select="element_collection/element[key('type1', index) and key('type2', index)]" />
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="element">
      <xsl:if test="position() > 1">, </xsl:if>
      <xsl:value-of select="index" />
  </xsl:template>
</xsl:stylesheet>