Reputation: 447
I want to make the following for-each work.
<xsl:for-each select="DATA[not(SUB1 and SUB2)
or ((SUB1 or SUB2) and count(//PERSON[SUB1=current()/SUB1 and SUB2=current()/SUB2] )=0)]">
It is grammatically correct but it does not work. I tried adding a dot after current()
, but it does not work either.
<xsl:for-each select="DATA[not(SUB1 and SUB2)
or ((SUB1 or SUB2) and count(//PERSON[SUB1=current()/./SUB1 and SUB2=current()/./SUB2])=0 )]">
I have the feeling that the problem is the current()
. It does not work with self::
either. I want the current()/SUB1
refers to the sub-node of DATA.
If I remove the test from <xsl:for-each>
and put it in an <xsl:if>
after the for-each I can make it work fine. It does not in the for-each statement.
<xsl:for-each select="DATA">
<xsl:if test="not(SUB1 and SUB2) or ((SUB1 or SUB2) and count(//PERSON[SUB1=current()/SUB1 and SUB2=current()/SUB2])=0)">
....
</xsl:if>
</xsl:for-each>
This is a test XML:
<ROOT>
<PERSON>
<SUB1>11</SUB1>
<SUB2>AA</SUB2>
</PERSON>
<PERSON>
<SUB1>22</SUB1>
<SUB2>BB</SUB2>
</PERSON>
<DATA>
<SUB1>99</SUB1>
<SUB2>ZZ</SUB2>
</DATA>
<DATA>
<SUB1>22</SUB1>
<SUB2>BB</SUB2>
</DATA>
<DATA>
</DATA>
</ROOT>
it should select these <DATA>
blocks since one has no SUB sub-nodes and the other has but there is no person with those SUB values:
<DATA>
<SUB1>99</SUB1>
<SUB2>ZZ</SUB2>
</DATA>
<DATA>
</DATA>
Upvotes: 0
Views: 46
Reputation: 8068
Using XSLT 2.0:
<xsl:template match="ROOT">
<xsl:apply-templates select="DATA" />
</xsl:template>
<xsl:template
match="DATA[empty(SUB1) and empty(SUB2)] |
DATA[SUB1 or SUB2]
[every $data in .
satisfies empty(/ROOT/PERSON[SUB1=$data/SUB1 and SUB2=$data/SUB2])]">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="DATA" />
Using XSLT 1.0 or XSLT 2.0 (and likely to be more efficient for a large number of PERSON):
<xsl:key name="person"
match="PERSON"
use="concat(SUB1, '', SUB2)" />
<xsl:template match="ROOT">
<xsl:apply-templates select="DATA" />
</xsl:template>
<xsl:template
match="DATA[not(SUB1) and not(SUB2)] |
DATA[SUB1 or SUB2]
[not(key('person', concat(SUB1, '', SUB2)))]">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="DATA" />
Upvotes: 1