Проверьте, появляется ли строка в значении узла в XSLT - PullRequest
0 голосов
/ 27 сентября 2011

У меня есть следующий XML:

<nodes>
  <node>
    <articles>125,1,9027</articles>
  </node>
  <node>
    <articles>999,48,123</articles>
  </node>
  <node>
    <articles>123,1234,4345,567</articles>
  </node>
</nodes>

Мне нужно написать некоторый XSLT, который будет возвращать только узлы с определенным идентификатором статьи, поэтому в приведенном выше примере только те узлы, которые содержат статью 123.

Мой XSLT не очень хорош, поэтому я борюсь с этим.Я хотел бы сделать что-то вроде этого, но я знаю, конечно, что в XSLT нет метода расширения 'instring':

<xsl:variable name="currentNodeId" select="1234"/>

<xsl:for-each select="$allNodes [instring(articles,$currentNodeId)]">
  <!-- Output stuff -->
</xsl:for-each>

Я знаю, что это хакерский, но не уверен в лучшем подходе крешать это.Набор узлов, вероятно, будет огромным, и число идентификаторов статей внутри узлов также, вероятно, будет огромным, поэтому я вполне уверен, что превращение этого разделения значения узла и превращение его в набор узлов - это не 'Это будет очень эффективно, но я могу ошибаться!

Любая помощь в том, как лучше всего это сделать, будет высоко оценена, спасибо.

Ответы [ 2 ]

1 голос
/ 27 сентября 2011

XSLT 2.0: Это будет соответствовать статьям, которые имеют точно 123 где-то в виде текста.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="id" select="123"/>

<xsl:template match="/">
    <xsl:for-each select="//node[matches(articles, concat('(^|\D)', $id, '($|\D)'))]">
      <xsl:value-of select="current()"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Пример ввода:

<?xml version="1.0" encoding="utf-8"?>
<nodes>
  <node>
    <articles>1234,1000,9027</articles>
  </node>
  <node>
    <articles>999,48,01234</articles>
  </node>
  <node>
    <articles>123,1234,4345,567</articles>
  </node>
  <node>
    <articles> 123 , 456 </articles>
  </node>
</nodes>

Вывод:

123,1234,4345,567

 123 , 456 

Я не знаю, как сделать это эффективно с XSLT 1.0, но, как сказал OP, он использует XSLT 2.0, так что это должен быть достаточный ответ.

0 голосов
/ 27 сентября 2011

В XSLT 1.0 вы можете использовать это простое решение, оно использует функции normalize-space, translate, contains, substring, string-length.

Пример ввода XML:

<nodes>
  <node>
    <articles>125,1,9027</articles>
  </node>
  <node>
    <articles>999,48,123</articles>
  </node>
  <node>
    <articles>123,1234,4345,567</articles>
  </node>
  <node>
    <articles> 123 , 456 </articles>
  </node>
  <node>
    <articles>789, 456</articles>
  </node>
  <node>
    <articles> 123 </articles>
  </node>
  <node>
    <articles>456, 123 ,789</articles>
  </node>
</nodes>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="id" select="123"/>

  <xsl:template match="node">
    <xsl:variable name="s" select="translate(normalize-space(articles/.), ' ', '')"/>

    <xsl:if test="$s = $id 
            or contains($s, concat($id, ','))
            or substring($s, string-length($s) - string-length($id) + 1, string-length($id)) = $id">
      <xsl:copy-of select="."/>
    </xsl:if>


  </xsl:template>

  <xsl:template match="/nodes">
    <xsl:copy>
      <xsl:apply-templates select="node"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Выход:

<nodes>
  <node>
    <articles>999,48,123</articles>
  </node>
  <node>
    <articles>123,1234,4345,567</articles>
  </node>
  <node>
    <articles> 123 , 456 </articles>
  </node>
  <node>
    <articles> 123 </articles>
  </node>
  <node>
    <articles>456, 123 ,789</articles>
  </node>
</nodes>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...