XSLT match multiple condition

I would like to filter nodes based on multiple condition.

<SHOP>
   <zasoba>
      <kod>10000</kod>
      <vyrobca>APPLE</vyrobca>
      <kategorie>
         <kategoria>GOOD</kategoria>
      </kategorie>
      <obrazky/>
   </zasoba>
   <zasoba>
      <kod>365</kod>
      <vyrobca>HUAWEI</vyrobca>
      <kategorie>
         <kategoria>SOMETHING</kategoria>
      </kategorie>
   </zasoba>
   <zasoba>
      <kod>999</kod>
      <vyrobca>HUAWEI</vyrobca>
      <kategorie>
         <kategoria>SOMETHING</kategoria>
      </kategorie>
   </zasoba>
   <zasoba>
      <kod>90000</kod>
      <vyrobca>APPLE</vyrobca>
      <kategorie>
         <kategoria>SECONDGOOD</kategoria>
      </kategorie>
      <obrazky/>
   </zasoba>
   <zasoba>
      <kod>304-R-MK</kod>
      <vyrobca>APPLE</vyrobca>
      <kategorie>
         <kategoria>NOTGOOD</kategoria>
      </kategorie>
   </zasoba>
</SHOP>

Condition:

Example output from input above:

<SHOP>
   <zasoba>
      <kod>10000</kod>
      <vyrobca>APPLE</vyrobca>
      <kategorie>
         <kategoria>GOOD</kategoria>
      </kategorie>
      <obrazky/>
   </zasoba>
   <zasoba>
      <kod>365</kod>
      <vyrobca>HUAWEI</vyrobca>
      <kategorie>
         <kategoria>SOMETHING</kategoria>
      </kategorie>
   </zasoba>
   <zasoba>
      <kod>999</kod>
      <vyrobca>HUAWEI</vyrobca>
      <kategorie>
         <kategoria>SOMETHING</kategoria>
      </kategorie>
   </zasoba>
   <zasoba>
      <kod>90000</kod>
      <vyrobca>APPLE</vyrobca>
      <kategorie>
         <kategoria>SECONDGOOD</kategoria>
      </kategorie>
      <obrazky/>
   </zasoba>
</SHOP>

I am trying to use this match:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" indent="yes" method="xml"/>

    <xsl:strip-space elements="*" />

    <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
    </xsl:template>

 <xsl:template match="zasoba[(not(vyrobca = 'APPLE') and not(kategorie/kategoria = 'GOOD' or kategorie/kategoria = 'SECONDGOOD')) or not(vyrobca = 'HUAWEI')]" />
</xsl:stylesheet>

But doesn't work. Operators can't be combined this way? I thought that (not(vyrobca = 'APPLE') and not(kategorie/kategoria = 'GOOD' or kategorie/kategoria = 'SECONDGOOD')) should work, where I made exception for APPLE and the two categories.

Upvotes: 2

Views: 549

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116992

Try this as your 2nd template:

<xsl:template match="zasoba[not(vyrobca = 'APPLE' and (kategorie/kategoria = 'GOOD' or kategorie/kategoria = 'SECONDGOOD') or vyrobca = 'HUAWEI')]" />

Explanation:

You want to include zasoba nodes that meet the following conditions:

vyrobca = 'APPLE' and (kategorie/kategoria = 'GOOD' or kategorie/kategoria = 'SECONDGOOD') 
or 
vyrobca = 'HUAWEI'

In order to rewrite this as the predicate for the nodes to exclude, we just need to wrap the entire expression in not().

You have:

(not(vyrobca = 'APPLE') and not(kategorie/kategoria = 'GOOD' or kategorie/kategoria = 'SECONDGOOD')) or not(vyrobca = 'HUAWEI')

To understand this better, let's drop the part about kategorie/kategoria and the redundant parentheses. This leaves as with:

not(vyrobca = 'APPLE') or not(vyrobca = 'HUAWEI')

which, according to DeMorgan's laws, is the equivalent of:

not ( vyrobca = 'APPLE' and vyrobca = 'HUAWEI' )

and this is of course true for any product with a single manufacturer.

Upvotes: 2

Related Questions