XSLT与不同条件匹配

时间:2018-08-22 09:54:02

标签: xml xslt

我需要根据输入xml的内容标签输出不同的节点。

正如您将在转换中看到的那样,我想认识到,如果关闭的SHU_CODE = 10、6、7、8、9,它应该进入一个NODE节点,但是如果它的SHU_CODE = 4,它应该进入一个节点。进入一个单独的节点。

然后在每个节点中,我将转换应用于每个特定的关闭。

我遇到的问题是我无法设法拥有单独的节点,所有节点都转到相同的节点。

这是输入xml:

  <Inserts>
    <Shuts>
      <Shut>
        <SHU_CODE>10</SHU_CODE>
      </Shut>
      <Shut>
        <SHU_CODE>4</SHU_CODE>
      </Shut>
    </Shuts>
  </Inserts>

这是我的预期输出:

<NODE>
    <SHUT workcenter='10'/>
</NODE>
<NODE>
    <SHUT workcenter='4'/>
</NODE>

这是我的xsl转换的一部分:

<xsl:template match="Inserts/Shuts[Shut/SHU_CODE='10'] 
    | Inserts/Shuts[Shut/SHU_CODE='6'] 
    | Inserts/Shuts[Shut/SHU_CODE='7']
    | Inserts/Shuts[Shut/SHU_CODE='8']
    | Inserts/Shuts[Shut/SHU_CODE='9']">
    <xsl:text>&#xa;</xsl:text>
    <xsl:text disable-output-escaping="yes">&lt;</xsl:text>NODE<xsl:text 

disable-output-escaping="yes">&gt;</xsl:text>
        <xsl:text>&#xa;</xsl:text>
            <xsl:apply-templates select="Shut[SHU_CODE='10'] 
| Shut[SHU_CODE='6'] 
| Shut[SHU_CODE='7'] 
| Shut[SHU_CODE='8'] 
| Shut[SHU_CODE='9']"/>
        <xsl:text disable-output-escaping="yes">&lt;/</xsl:text>NODE<xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    </xsl:template>

<xsl:template match="Inserts/Shuts[Shut/SHU_CODE='4']">
    <xsl:text>&#xa;</xsl:text>
    <xsl:text disable-output-escaping="yes">&lt;</xsl:text>NODE<xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    <xsl:text>&#xa;</xsl:text>
        <xsl:apply-templates select="Shut[SHU_CODE='4']"/>
    <xsl:text disable-output-escaping="yes">&lt;/</xsl:text>NODE<xsl:text disable-output-escaping="yes">&gt;</xsl:text>
</xsl:template>

1 个答案:

答案 0 :(得分:0)

假设您可以移至XSLT 2或3,则可以使用xsl:for-each-group轻松完成此操作:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Shuts">
      <xsl:for-each-group select="Shut" group-by="SHU_CODE = 4">
          <NODE>
              <xsl:apply-templates select="current-group()"/>
          </NODE>
      </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="Shut">
      <SHUT workcenter="{SHU_CODE}"/>
  </xsl:template>


</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/eiZQaFB有一个在线示例。在XSLT 1中,通常使用Muenchian分组和一个密钥进行分组。

如果要基于不同的值形成不同的组,则需要某种方式来定义这些组,假设具有XPath 3.1的XSLT 3可以使用一系列数组,然后在其中检查索引。 https://xsltfiddle.liberty-development.net/eiZQaFB/1

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs array mf"
    version="3.0">

  <xsl:param name="group-keys" as="array(xs:integer)*" select="[4], [11], array{6 to 10}"/>

  <xsl:function name="mf:group-index" as="xs:integer">
      <xsl:param name="seq-of-arrays" as="array(xs:integer)*"/>
      <xsl:param name="code" as="xs:integer"/>
      <xsl:sequence select="for $pos in 1 to count($seq-of-arrays)
                            return $pos[array:flatten($seq-of-arrays[$pos]) = $code]"/>
  </xsl:function>

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Shuts">
      <xsl:for-each-group select="Shut" group-by="mf:group-index($group-keys, SHU_CODE)">
          <NODE>
              <xsl:apply-templates select="current-group()"/>
          </NODE>
      </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="Shut">
      <SHUT workcenter="{SHU_CODE}"/>
  </xsl:template>

</xsl:stylesheet>