xml - XSLT 2.0 Compare sequence of attribute values to variable -


i have elements such as

<elem attr1="value1 somevalue" attr2="value2 someothervalue"/> 

elements variable amount of attributes each have variable amount of values.

some of these attributes' names , of values saved in variables beforehand , elements checked against these variables.

i need check if element has attributes specified in variable (which got working) , if each attribute, @ least 1 of values 1 of values specified in variable.

so if variable contains "value1 value2" (or more values)

the element

<elem attr1="value1 somevalue" attr2="value1 someothervalue athirdvalue" attr3="value2 othervalue"/>

meets requirements (provided attr1, attr2 , attr3 correct attribute names, check before), element:

<elem attr1="value1 somevalue" attr2="anything someothervalue" attr3="value othervalue"/>

doesn't meet requirements, because 1 of attributes has no value contained in variable (attr2: neither anything nor someothervalue specified in variable).

i tried tokenizing values, elemens considered correct if 1 attribute has 1 of correct values. need make sure, of attributes have @ least 1 of correct values.

help , tips highly appreciated!

edit:

the way values of variable 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 @ filters elements above, elems can this:

<elem/> <!-- no attribute --> <elem someattr="somevalue"/> <!-- irrelevant attribute --> <elem attr1="value1"/> <!-- 1 of attributes --> <elem attr1="value1" attr2="value"/> <!-- 2 of attributes --> 

so @name attribute of filters element specifies name of attribute on elem element , @value attribute of filters element specifies value that attribute must have in order meet requirements.

solution (adapted answer post)

<xsl:when test="count(@*[local-name() = $filternames]) > 1"> <!-- element has more 1 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">             <!-- @ least 1 attribute doesnt have of required values -->         </xsl:when>         <xsl:otherwise>             <!-- attributes have @ least 1 of 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> 

this bit abstract, demonstrate principle, let have following:

xml

<root>     <elem attr1="alpha charlie" attr2="delta alpha echo" attr3="foxtrot bravo golf"/>     <elem attr1="alpha charlie" attr2="hotel delta" attr3="bravo india"/>  </root> 

xslt 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>  <xsl:variable name="values" select="('alpha', 'bravo')"/>  <xsl:template match="/root">     <xsl:copy>         <xsl:apply-templates select="elem"/>     </xsl:copy> </xsl:template>       <xsl:template match="elem">     <xsl:copy>         <xsl:choose>             <xsl:when test="@*[not(tokenize(., ' ')=$values)]">                 <xsl:text>no</xsl:text>             </xsl:when>             <xsl:otherwise>                 <xsl:text>yes</xsl:text>             </xsl:otherwise>         </xsl:choose>     </xsl:copy> </xsl:template>  </xsl:stylesheet> 

result

<?xml version="1.0" encoding="utf-8"?> <root>    <elem>yes</elem>    <elem>no</elem> </root> 

explanation

the test:

test="@*[not(tokenize(., ' ')=$values)]" 

returns true when there @ least 1 attribute that, after tokenizing, not contain token matches 1 of values in $values variable.


edit

in response modified requirements, believe should work:

xslt 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>  <xsl:variable name="filter-doc" select="document('filter.xml')"/>  <xsl:key name="filter-by-name" match="filters" use="@name" />  <xsl:template match="/root">     <xsl:copy>         <xsl:apply-templates select="elem"/>     </xsl:copy> </xsl:template>       <xsl:template match="elem">     <xsl:variable name="strikes">         <xsl:for-each select="@*[key('filter-by-name', name(), $filter-doc)]">             <xsl:variable name="values" select="key('filter-by-name', name(), $filter-doc)/@value" />             <xsl:if test="not(tokenize(., ' ')=$values)">                 <strike/>             </xsl:if>         </xsl:for-each>     </xsl:variable>      <xsl:copy>         <xsl:choose>             <xsl:when test="$strikes/strike">                 <xsl:text>no</xsl:text>             </xsl:when>             <xsl:otherwise>                 <xsl:text>yes</xsl:text>             </xsl:otherwise>         </xsl:choose>     </xsl:copy> </xsl:template>  </xsl:stylesheet> 

this streamlined bit, first know if provides correct answers.


Comments

Popular posts from this blog

javascript - oscilloscope of speaker input stops rendering after a few seconds -

javascript - gulp-nodemon - nodejs restart after file change - Error: listen EADDRINUSE events.js:85 -

Fatal Python error: Py_Initialize: unable to load the file system codec. ImportError: No module named 'encodings' -