At 14:42 19/04/2003 -0500, you wrote:
I am trying to find all the attributes in an XML document that contain a
particular value.
Given the following data...
<ExampleData>
<NodeA name="foo"/>
<NodeA name="larry"/>
<NodeA name="foo"/>
<NodeB author="foo"/>
<NodeB author="larry"/>
<NodeC reporter="foo"/>
</ExampleData>
I would like to write an XPATH statement that returns this:
<NodeA name="foo"/>
<NodeB author="foo"/>
<NodeC reporter="foo"/>
Note that I am only returning UNIQUE instances of element/attribute
combinations with the attribute value.
Is this possible using XPATH?
Larry,
Perhaps you are looking for a more general solution, or perhaps you are
seeking a solution which has to be accomplished inside a single XPath
expression.
The following style sheet takes your data as input and produces the
specified data as output (only modified to produce well-formed XML).
<?xml version='1.0'?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="/">
<ExampleData>
<xsl:apply-templates select="ExampleData/*[(_at_)*='foo']" />
</ExampleData>
</xsl:template>
<xsl:template match="*">
<xsl:if test="not( name(.)=name(preceding-sibling::*) )" >
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The predicate in the select attribute of <xsl:apply-templates> selects only
elements with an attribute containing the desired value.
The value of the test attribute on <xsl:if> tests whether or not an element
with the same name (and because of the way that <xsl:apply-templates> is
used, and which also has an attribute with value of "foo") is a preceding
sibling. If such a preceding sibling exists, no output is produced.
Implicitly the solution assumes that there can be only one attribute on any
particular element type that can have the value of "foo". It wouldn't work,
as written, if for example <NodeA> could have a name attribute or a
reporter attribute each of which could take a value of "foo". It would only
display the first <NodeA> attribute which possesed an attribute with value
of "foo".
If you want to look for uniqueness in the document, rather than uniqueness
among siblings, you might use the preceding axis rather than the
preceding-sibling axis.
Andrew Watt
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list