Reputation: 33
Don't know how to clearly explain it, so I'll just give an example: xml file:
<root>
<one>
<a a="x"/>
<a a="y"/>
</one>
<two>
<a a="x"/>
<a a="y"/>
</two>
</root>
and here's an xsl:
<xsl:template match="/root">
<xsl:variable name="self" select="."/>
<xsl:if test="one/a/@a = $self/two/*/a/@a">
<xsl:text>it works</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I just want the if to work...
//edit
An explanation:
<requirements>
<bar/><restaurant/>
</requirements>
<offer>
<bar/></beach><restaurant/><nightclub/>
<offer>
so i want the 'if' to check if all (in this case) elements of 'requirements' are satisfied by the elements of 'offer'
Upvotes: 1
Views: 682
Reputation: 243599
Use this XPath 2.0 expression:
not($requirements[not(name()=$offer/name())])
where:
$requirements
is /*/requirements/*
and
$offer
is /*/offer/*
and these are evaluated against the XML document below (essentially the provided non-wellformed XML made well-formed XML document):
<t>
<requirements>
<bar/>
<restaurant/>
</requirements>
<offer>
<baz/>
<beach/>
<restaurant/>
<nightclub/>
</offer>
</t>
The same technique for your initial problem:
not(/*/one/a[not(@a = /*/two/a/@a)])
Note that the above is a one-lener XPath 1.0 solution. : )
Upvotes: 1
Reputation:
This XSLT 1.0 stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kElementByName" match="requirements/*" use="name()"/>
<xsl:template match="offer[count(*[key('kElementByName',name())])
= count(../requirements/*)]">
<xsl:text>Success!</xsl:text>
</xsl:template>
</xsl:stylesheet>
With this input (well formed):
<root>
<requirements>
<bar/>
<restaurant/>
</requirements>
<offer>
<bar/>
<beach/>
<restaurant/>
<nightclub/>
</offer>
</root>
Output:
Success!
Note: The use of xsl:key
because functions implicit node set casting to scalar only takes the first node.
XPath 2.0 expression:
every $name in /root/requirements/*/name()
satisfies $name = /root/offer/*/name()
Upvotes: 1
Reputation: 5892
EDIT
XSLT 1.0 Solution:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="validTest">
<xsl:for-each select="/*/requirements/*">
<xsl:value-of select="concat(name(),'+')"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="offer">
<xsl:if test="count(/*/requirements/*) = count(*[
contains($validTest,
concat(name(),'+')
)
])">
<xsl:value-of select="concat('#', @id, ' is a valid offer!
')"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Applied to the XML sample:
<root>
<requirements>
<bar/><restaurant/>
</requirements>
<offer id="1">
<bar/><beach/><restaurant/><nightclub/>
</offer>
<offer id="2">
<bar/><beach/><nightclub/>
</offer>
<offer id="2">
<beach/><nightclub/><restaurant/>
</offer>
<offer id="4">
<bar/><beach/><restaurant/><nightclub/>
</offer>
</root>
produces this result:
#1 is a valid offer!
#4 is a valid offer!
Upvotes: 0
Reputation: 163625
Perhaps you're looking for
test="every $x in $self/one/xxx satisfies some $y in $self/two/yyy satisfies $x = $y"
Upvotes: 0
Reputation: 22064
Perhaps this?
<xsl:template match="/root">
<xsl:variable name="self" select="."/>
<xsl:variable name="aKey" select="one/a/@a"/>
<xsl:if test="$self/two/*/a[@a=$aKey]">
<xsl:text>it works</xsl:text>
</xsl:if>
</xsl:template>
Upvotes: 0