Reputation: 329
I have a simple kind of layout like the following:
<SubSection filter="filter14, filter13, filter12">
<SubSection>
<para> test </para>
</SubSection>
<SubSection filter="filter1">
<Reviewer>John Smith</Reviewer>
</SubSection>
</SubSection>
I am using part of the DocBook profile xsl to pull out, in this case, SubSection elements that have filter='filter14', however, i also want to pull out any elements that have filter='filter1' if they are an ancestor of an element having a filter='filter14' value.
I am using the following test, which works excepts for the test for 'filter1' value:
<!-- Copy all non-element nodes -->
<xsl:template match="@*|text()|comment()|processing-instruction()" node="profile">
<xsl:copy/>
</xsl:template>
<!-- Profile elements based on input parameters -->
<xsl:template match="*" mode="profile">
<!-- This is my input for a filter attribute RU -->
<xsl:variable name="filter.content">
<xsl:if test="@filter">
<xsl:call-template name="cross.compare">
<!-- <xsl:with-param name="a" select="$profile.filter"/> -->
<xsl:with-param name="a" select="'filter14'"/>
<xsl:with-param name="b" select="@filter"/>
</xsl:call-template>
</xsl:if>
</xsl:variable>
<xsl:variable name="filter.ok" select="not(@filter) or
$filter.content != '' or @filter = '' or (@filter = 'filter1' and contains(ancestor::SubSection[@filter], 'filter14'))"/>
<xsl:if test="$filter.ok">
<xsl:copy>
<xsl:apply-templates mode="profile" select="@*"/>
<xsl:apply-templates select="node()" mode="profile"/>
</xsl:copy>
</xsl:if>
</xsl:template>
And cross.compare is:
<!-- Returns non-empty string if list in $b contains one ore more values from list $a -->
<xsl:template name="cross.compare">
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:param name="sep" select="$profile.separator"/>
<xsl:variable name="head" select="substring-before($b, $a)"/>
<xsl:variable name="tail" select="substring-after($b, $a)"/>
<xsl:if test="contains($b, $a)">1</xsl:if>
</xsl:template>
It seems that this is just finding the right xpath for checking to see if the current element filter attribute = 'filter1' and the ancestor SubSection element filter attribute contains 'filter14'. I would think this would work, but it isn't.
I am still getting everything with a 'filter14' filter attribute value, as well and any elements not having a filter attribute or a filter attribute value of '', but not one with a filter attribute value of 'filter1'.
Can anyone suggest what is happening here?
Thanks,
Russ
Upvotes: 1
Views: 1792
Reputation: 101700
Looks like this is where you've gone wrong:
contains(ancestor::SubSection[@filter], 'filter14')
This says "find the first SubSection
ancestor that has a @filter
attribute and produce true
if it contains 'filter14'`.
What you need instead is this:
ancestor::SubSection[contains(@filter, 'filter14')]
Slightly more robust version:
ancestor::SubSection[contains(concat('|', normalize-string(@filter), '|'), '|filter14|')]
Upvotes: 2