Reputation: 193
I have an XML document as follows:
<Document>
<Countries>
<Country>Scotland</Country>
<Country>England</Country>
<Country>Wales</Country>
<Country>Northern Ireland</Country>
</Countries>
<Populations>
<Population country="Scotland" value="5" />
<Population country="England" value="53" />
<Population country="Wales" value="3" />
<Population country="Northern Ireland" value="2" />
<Population country="France" value="65" />
<Population country="" value="35" />
</Populations>
</Document>
I am attempting to write an XSLT statement which will access all Population elements where its "country" attribute is blank OR its "country" attribute is NOT in /Document/Countries/Country
My XSLT looks as follows:
<xsl:variable name="countries" select="/Document/Countries/Country" />
<xsl:variable name="populations" select="/Document/Populations/Population" />
<xsl:variable name="populationsNotInList" select="$populations[(@country = '') OR (@country NOT IN $countries)" />
Can you help me fill in the 'NOT IN $countries' part of the $populationsNotInList variable?
I am essentially looking for an output of:
<Population country="France" value="65" />
<Population country="" value="35" />
Upvotes: 0
Views: 7608
Reputation: 22617
If you do not necessarily need to store them in a variable, this is how you can access the relevant nodes.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Document">
<xsl:for-each select="Populations/Population">
<xsl:if test="@country = '' or not(../../Countries/Country[.=current()/@country])">
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="Country"/>
</xsl:stylesheet>
This gives you the following output (assuming correct input - your input XML is not correct):
<?xml version="1.0" encoding="UTF-8"?>
<Population country="France" value="65"/>
<Population country="" value="35"/>
Upvotes: 1
Reputation: 167651
Use <xsl:variable name="populationsNotInList" select="$populations[(@country = '') or not(@country = $countries)" />
or better define a key
<xsl:key name="country" match="Countries/Country" use="."/>
then you can do <xsl:variable name="populationsNotInList" select="$populations[(@country = '') or not(key('country', @country))" />
Upvotes: 2