Захват позиции узла, отфильтрованного из условия IF в XSLT v1.0 - PullRequest
0 голосов
/ 25 октября 2018

Ниже мой вклад.После преобразования я хочу, чтобы первое значение, отфильтрованное по условию, было напечатано в «первом» элементе, а оставшееся было напечатано в элементе «rest».

Входной XML:

<root>
    <a>0</a>
    <a>0</a>
    <a>0</a>
    <a>0</a>
    <a>5</a>
    <a>6</a>
    <a>7</a>
    <a>0</a>
    <a>9</a>
    <a>0</a>
    <a>11</a>
    <a>12</a>
    <a>0</a>
    <a>0</a>
    <a>15</a>
    <a>16</a>
</root>

В следующем XSLT, скажем, обязательно иметь условия for-each и if внутри.Поскольку положение захватывает на уровне для каждого, первый вход, отфильтрованный через условие if, не находится в положении 1, что приводит к нежелательному выводу.

XSLT:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <root>
            <xsl:for-each select="root/a">
                **<xsl:if test=". != 0">**
                    <xsl:choose>
                        <xsl:when test="position()=1">
                            <first-value>
                                <xsl:value-of select="." />
                            </first-value>
                        </xsl:when>
                        <xsl:otherwise>
                            <rest>
                                <xsl:value-of select="." />
                            </rest>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

Вывод из вышеупомянутого XSLT

<root>
    **<rest>5</rest>**
    <rest>6</rest>
    <rest>7</rest>
    <rest>9</rest>
    <rest>11</rest>
    <rest>12</rest>
    <rest>15</rest>
    <rest>16</rest>
</root>

Ожидаемый вывод:

<root>
    **<first>5</first>**
    <rest>6</rest>
    <rest>7</rest>
    <rest>9</rest>
    <rest>11</rest>
    <rest>12</rest>
    <rest>15</rest>
    <rest>16</rest>
</root>

Как напечатать первое отфильтрованное значение вэлемент, а остальные в отдельном элементе?Есть ли альтернативный подход к тому, что я выбрал?

Ответы [ 4 ]

0 голосов
/ 25 октября 2018

Вы можете использовать так:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs" version="1.0">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="root">
        <root>
            <xsl:for-each select="a[.!=0]">
                <xsl:choose>
                    <xsl:when test="position()=1">
                        <first><xsl:value-of select="."/></first>
                    </xsl:when>
                    <xsl:otherwise>
                        <rest><xsl:value-of select="."/></rest>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </root>
    </xsl:template>

</xsl:stylesheet>
0 голосов
/ 25 октября 2018

Вы можете использовать переменную, хранящую <xsl:number count="a[. != 0]"/> и сравнивающую это:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <root>
            <xsl:for-each select="root/a">
                <xsl:if test=". != 0">
                    <xsl:variable name="a-unequal-zero-index">
                      <xsl:number count="a[. != 0]"/>
                    </xsl:variable>
                    <xsl:choose>
                        <xsl:when test="$a-unequal-zero-index =1 ">
                            <first-value>
                                <xsl:value-of select="." />
                            </first-value>
                        </xsl:when>
                        <xsl:otherwise>
                            <rest>
                                <xsl:value-of select="." />
                            </rest>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

Является ли это все идиоматическим способом XSLT. Я не уверен, вы не предоставили никакого контекста, объясняющегоиспользование for-each, а затем вложение if и choose.

https://xsltfiddle.liberty -development.net / gWmuiK8 / 1 имеет интерактивный образец.

0 голосов
/ 25 октября 2018

Сработало следующее ..

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" />
        <xsl:template match="/">
            <root>
                <xsl:for-each select="root/a[. != 0]">
                        <xsl:choose>
                            <xsl:when test="position()= 1">
                                <first><xsl:value-of select="." /></first>
                            </xsl:when>
                            <xsl:otherwise>
                                <rest>
                                    <xsl:value-of select="." />
                                </rest>
                            </xsl:otherwise>
                        </xsl:choose>
                </xsl:for-each>
            </root>
        </xsl:template>
    </xsl:stylesheet>
0 голосов
/ 25 октября 2018
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <root>
        <xsl:for-each select="root/a">
            **<xsl:if test=". != 0">**
                <xsl:choose>
                    <xsl:when test="not(max(preceding-sibling::a) > 0)">
                        <first-value>
                            <xsl:value-of select="." />
                        </first-value>
                    </xsl:when>
                    <xsl:otherwise>
                        <rest>
                            <xsl:value-of select="." />
                        </rest>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:if>
        </xsl:for-each>
    </root>
</xsl:template>

...