I have elements such as
<elem attr1="value1 someValue" attr2="value2 someOtherValue"/>
elements with a variable amount of attributes that each have a variable amount of values.
Some of these attributes' names and some of their values are saved in variables beforehand and the elements are checked against these variables.
I need to check if the element has attributes specified in that variable (which I got working) and if for each attribute, at least one of its values is one of the values specified in another variable.
So if the variable contains "Value1 Value2
" (or more values)
The element
<elem attr1="Value1 SomeValue" attr2="Value1 someOtherValue AthirdValue" attr3="value2 otherValue"/>
meets the requirements (provided that attr1, attr2 and attr3 are the correct attribute names, which I check before), but element:
<elem attr1="Value1 SomeValue" attr2="anything someOtherValue" attr3="value otherValue"/>
doesn't meet the requirements, because one of the attributes has no value that is contained in the variable (attr2
: neither anything
nor someOtherValue
are specified in the variable).
I tried tokenizing the values, but then the elemens are considered correct even if only one attribute has one of the correct values. I need to make sure, all of the attributes have at least one of the correct values.
Help and tips highly appreciated!
EDIT:
The way the values of the variable are obtained:
<xsl:variable name="filterName" select="$someDoc//someElem[@id = $curID]//filters/@value"/>
The other document:
<?xml version="1.0"/>
<doc>
<filters name="attr1" value="value1"/>
<filters name="attr2" value="value2"/>
<filters name="attr3" value="value2"/>
</doc>
**EDIT 2:**
Looking at the filters elements above, the elems can look like this:
<elem/> <!-- no attribute -->
<elem someattr="somevalue"/> <!-- some irrelevant attribute -->
<elem attr1="value1"/> <!-- one of the attributes -->
<elem attr1="value1" attr2="value"/> <!-- two of the attributes -->
So the @name
attribute of the filters
element specifies the name of the attribute on the elem
element and the @value
attribute of the filters element specifies the value that that attribute must have in order to meet the requirements.
SOLUTION (adapted from answer post)
<xsl:when test="count(@*[local-name() = $filterNames]) > 1">
<!-- element has more then one filter attribute -->
<xsl:variable name="currentFilterValues">
<xsl:value-of select="$filterValues"/>
</xsl:variable>
<xsl:variable name="attributeNamesOfCurrentElement">
<xsl:value-of select="@*[local-name() = $filterNames]/fn:local-name()"/>
</xsl:variable>
<xsl:variable name="errors">
<xsl:for-each select="tokenize($attributeNamesOfCurrentElement, '\s+')">
<xsl:variable name="currentName" select="."/>
<xsl:variable name="currentValue" select="$currentElement/@*[fn:local-name() = $currentName]"/>
<xsl:if test="not(tokenize($currentValue, '\s+') = tokenize($currentFilterValues, ' '))">
<error/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="$errors/error">
<!-- at least one attribute doesnt have any of the required values -->
</xsl:when>
<xsl:otherwise>
<!-- all attributes have at least one of the required values -->
<xsl:copy>
<xsl:apply-templates select="$currentElement_2/@*"/>
<xsl:if test="child::*">
<xsl:for-each select="child::*">
<xsl:call-template name="recurse">
<xsl:with-param name="filterNames" select="$filterNames"/>
<xsl:with-param name="filterValues" select="$filterValues"/>
<xsl:with-param name="filterType" select="$filterType"/>
<xsl:with-param name="currentElement_2" select="."/>
</xsl:call-template>
</xsl:for-each>
</xsl:if>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:when>