Динамический оператор «соответствует» в XSLT

Я пытаюсь создать функцию xslt, которая динамически «соответствует» элементу. В функцию я передам два параметра — item()* и строку с разделителями-запятыми. Я обозначаю строку с разделителями-запятыми в операторе select <xsl:for-each>, а затем делаю следующее:

select="concat('$di:meta[matches(@domain,''', current(), ''')][1]')"

Вместо оператора select, «выполняющего» xquery, он просто возвращает строку.

Как я могу заставить его выполнить xquery?

Заранее спасибо!


person Sal Velazquez    schedule 18.05.2011    source источник


Ответы (1)


Проблема в том, что вы переносите слишком большую часть выражения в функцию concat(). Когда это оценивается, он возвращает строку, которая будет выражением XPath, а не оценивает выражение XPath, которое использует динамическую строку для выражения соответствия REGEX.

Вы хотите использовать:

 <xsl:value-of select="$di:meta[matches(@domain
                                        ,concat('.*('
                                                ,current()
                                                ,').*')
                                        ,'i')][1]" />

Хотя, поскольку теперь вы оцениваете каждый термин отдельно, вместо того, чтобы иметь каждый из этих терминов в одном шаблоне регулярного выражения и выбирать первый, он теперь будет возвращать первый результат из каждого совпадения, а не первый из последовательности сопоставленных Предметы. Это может быть или не быть тем, что вы хотите.

Если вам нужен первый элемент из последовательности совпадающих элементов, вы можете сделать что-то вроде этого:

<!--Create a variable and assign a sequence of matched items -->
<xsl:variable name="matchedMetaSequence" as="node()*">
 <!--Iterate over the sequence of names that we want to match on -->
 <xsl:for-each select="tokenize($csvString,',')">
  <!--Build the sequence(list) of matched items, 
      snagging the first one that matches each value -->
  <xsl:sequence select="$di:meta[matches(@domain
                       ,concat('.*('
                               ,current()
                               ,').*')
                       ,'i')][1]" />
 </xsl:for-each>
</xsl:variable>
<!--Return the first item in the sequence from matching on 
    the list of domain regex fragments -->
<xsl:value-of select="$matchedMetaSequence[1]" />

Вы также можете поместить это в пользовательскую функцию следующим образом:

<xsl:function name="di:findMeta">
 <xsl:param name="meta" as="element()*" />
 <xsl:param name="names" as="xs:string" />

 <xsl:for-each select="tokenize(normalize-space($names),',')">
  <xsl:sequence select="$meta[matches(@domain
                                      ,concat('.*('
                                              ,current()
                                              ,').*')
                                      ,'i')][1]" />
 </xsl:for-each>
</xsl:function>

а затем используйте его следующим образом:

 <xsl:value-of select="di:findMeta($di:meta,'foo,bar,baz')[1]"/>
person Mads Hansen    schedule 18.05.2011