XSLT-фильтр со счетчиком индексов - PullRequest
3 голосов
/ 23 марта 2009

Я написал некоторый XSLT, который использует один XML-документ для фильтрации другого. Теперь я хотел бы пронумеровать мои выходные элементы, используя position(), но мое условие фильтрации не встроено в мой <xsl:for-each>, поэтому position() дает мне результаты с пробелами в нумерации. Как мне избавиться от пробелов?

<xsl:variable name="Astring">
  <a><b>10</b><b>20</b><b>30</b></a>
</xsl:variable>
<xsl:variable name="A" select="msxml:node-set($Astring)" />

<xsl:variable name="Bstring">
  <c><d>20</d><d>30</d></c>
</xsl:variable>
<xsl:variable name="B" select="msxml:node-set($Bstring)" />

<e>
  <xsl:for-each select="$A/a/b">
    <xsl:variable name="matchvalue" select="text()" />
    <xsl:if test="count($B/c/d[text() = $matchvalue]) &gt; 0">
      <xsl:element name="f">
        <xsl:attribute name="i">
          <xsl:value-of select="position()" />
        </xsl:attribute>
        <xsl:copy-of select="text()" />
      </xsl:element>
    </xsl:if>
  </xsl:for-each>
</e>

Вот результат:

<e>
  <f i="2">20</f>
  <f i="3">30</f>
</e>

... но я хочу это:

<e>
  <f i="1">20</f>
  <f i="2">30</f>
</e>

Есть ли способ включить вышеупомянутый <xsl:if> тест фильтрации в атрибут <xsl:for-each> select?

Примечание: я видел этот вопрос re: filtering и this re: counters, но первый не нумерует свои результаты, а второй использует position ().

Ответы [ 2 ]

3 голосов
/ 23 марта 2009

Есть ли какая-то конкретная причина, по которой вы не можете включить свое условие в цикл for-each?

<xsl:for-each select="$A/a/b[$B/c/d = .]">

Я проверил это в Visual Studio, и он отлично работает в этом примере.

Это был вывод:

<e>
  <f i="1">20</f>
  <f i="2">30</f>
</e>
2 голосов
/ 23 марта 2009

Я не уверен, почему люди всегда хотят использовать <xsl:for-each>, когда <xsl:apply-templates> явно лучшая альтернатива.

Хорошо, это риторический вопрос. Я знаю, почему это так: <xsl:for-each> кажется проще. Но это не & mdash; следующие два шаблона заменяют всю конструкцию for-каждой:

<xsl:template match="/">
  <e><xsl:apply-templates select="$B/c/d[$A/a/b = .]" /></e>
</xsl:template>

<xsl:template match="d">
  <f i="{position()}"><xsl:value-of select="." /></f>
</xsl:template>

Выход:

<e>
  <f i="1">20</f>
  <f i="2">30</f>
</e>

Ну, я немного обманул. Вы можете сократить <xsl:for-each> версию до этого:

<xsl:template match="/">
  <e>
    <xsl:for-each select="$B/c/d[$A/a/b = .]">
      <f i="{position()}"><xsl:value-of select="." /></f>
    </xsl:for-each>
  </e>
</xsl:template>

Тем не менее, ему не хватает легкости <xsl:apply-templates> варианта, ИМХО.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...