user481779
user481779

Reputation: 1081

XSLT 2.0: How to determine at least one value exists or does not exist in list?

The XSLT and XML shown below generates the following output:

<CodeGroupA>Found</CodeGroupA>
<CodeGroupB>Not found</CodeGroupB>
<CodeGroupA>Found</CodeGroupA>
<CodeGroupB>Not found</CodeGroupB>
<CodeGroupA>Not found</CodeGroupA>
<CodeGroupB>Not found</CodeGroupB>

I need to generate this output:

<CodeGroupA>Found</CodeGroupA>
<CodeGroupB>Not found</CodeGroupB>

I attempted a number of different methods using recursion and for-each but I cannot figure it out. Any suggestion would be appreciated.

Thanks in advance.

Here is my XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:math="http://www.w3.org/2005/xpath-functions/math"
  xmlns:map="http://www.w3.org/2005/xpath-functions/map"
  xmlns:array="http://www.w3.org/2005/xpath-functions/array"
  exclude-result-prefixes="xs math map array"
  version="3.0">

  <!-- input/output configuration -->
  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*"/>

  <xsl:variable name="CodeGroupA" select="'12', '13'" />
  <xsl:variable name="CodeGroupB" select="'17', '18'" />

  <xsl:template match="/Diagnoses/Diagnosis" >

    <xsl:if test=".[Code=($CodeGroupA)]">
        <CodeGroupA>Found</CodeGroupA>
    </xsl:if>

    <xsl:if test="not(.[Code=($CodeGroupA)])">
        <CodeGroupA>Not found</CodeGroupA>
    </xsl:if>

    <xsl:if test=".[Code=($CodeGroupB)]">
        <CodeGroupB>Found</CodeGroupB>
    </xsl:if>

    <xsl:if test="not(.[Code=($CodeGroupB)])">
        <CodeGroupB>Not found</CodeGroupB>
    </xsl:if>
  </xsl:template>

  <xsl:template match="text()|@*">
  </xsl:template>

</xsl:stylesheet>

Here is my input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Diagnoses>
  <Diagnosis>
    <Code>12</Code>
  </Diagnosis>
  <Diagnosis>
    <Code>13</Code>
  </Diagnosis>
  <Diagnosis>
    <Code>14</Code>
  </Diagnosis>
</Diagnoses>

Upvotes: 0

Views: 1347

Answers (2)

Tim C
Tim C

Reputation: 70628

You should really match on the Diagnoses element, otherwise you will get something output for each Diagnosis which is not really what you want.

But if you do this, you can get the result you want by doing this...

<CodeGroupA>
    <xsl:value-of select="if (Diagnosis/Code=$CodeGroupA) then 'Found' else 'Not found'" />
</CodeGroupA>

And similarly for CodeGroupB.

Of course, you could avoid repeated logic by putting the logic in a function. Try this XSLT

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

  <!-- input/output configuration -->
  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*"/>

  <xsl:variable name="CodeGroupA" select="'12', '13'" />
  <xsl:variable name="CodeGroupB" select="'17', '18'" />

  <xsl:template match="/Diagnoses" >

    <CodeGroupA>
        <xsl:value-of select="my:check(Diagnosis/Code, $CodeGroupA)" />
    </CodeGroupA>

    <CodeGroupB>
        <xsl:value-of select="my:check(Diagnosis/Code, $CodeGroupB)" />
    </CodeGroupB>
  </xsl:template>

  <xsl:function name="my:check">
      <xsl:param name="nodes" />
      <xsl:param name="group" />
      <xsl:value-of select="if ($nodes = $group) then 'Found' else 'Not found'" />
  </xsl:function>
</xsl:stylesheet>

Upvotes: 2

Martin Honnen
Martin Honnen

Reputation: 167651

Change the context node for the tests:

  <xsl:template match="/Diagnoses" >

    <xsl:if test="Diagnosis/Code = $CodeGroupA">
        <CodeGroupA>Found</CodeGroupA>
    </xsl:if>

    <xsl:if test="not(Diagnosis/Code = $CodeGroupA)">
        <CodeGroupA>Not found</CodeGroupA>
    </xsl:if>

    <xsl:if test="Diagnosis/Code = $CodeGroupB">
        <CodeGroupB>Found</CodeGroupB>
    </xsl:if>

    <xsl:if test="not(Diagnosis/Code = $CodeGroupB)">
        <CodeGroupB>Not found</CodeGroupB>
    </xsl:if>
  </xsl:template>

https://xsltfiddle.liberty-development.net/bdxtq9

Upvotes: 1

Related Questions