Сравнивать два элемента (строковый тип) в XSLT? - PullRequest
16 голосов
/ 13 апреля 2011

Я новичок в XSLT. Может ли кто-нибудь предложить мне, как сравнить два элемента из xml в виде строки, значения которой:

<OU_NAME>Vision Operations</OU_NAME> --XML code
<OU_ADDR1>90 Fifth Avenue</OU_ADDR1> --XML code

<xsl:choose>
    <xsl:when test="OU_NAME='OU_ADDR1'"> --comparing two elements coming from XML
        <!--remove if  adrees already contain  operating unit name
            <xsl:value-of select="OU_NAME"/> <fo:block/>-->
        <xsl:if test="OU_ADDR1 !='' ">
            <xsl:value-of select="OU_ADDR1"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="LE_ADDR2 !='' ">
            <xsl:value-of select="OU_ADDR2"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="LE_ADDR3 !='' ">
            <xsl:value-of select="OU_ADDR3"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="OU_TOWN_CITY !=''">
            <xsl:value-of select="OU_TOWN_CITY"/>,
            <fo:leader leader-pattern="space" leader-length="2.0pt"/>
        </xsl:if>
        <xsl:value-of select="OU_REGION2"/>
        <fo:leader leader-pattern="space" leader-length="3.0pt"/>
        <xsl:value-of select="OU_POSTALCODE"/>
        <fo:block/>
        <xsl:value-of select="OU_COUNTRY"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="OU_NAME"/>
        <fo:block/>
        <xsl:if test="OU_ADDR1 !='' ">
            <xsl:value-of select="OU_ADDR1"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="LE_ADDR2 !='' ">
            <xsl:value-of select="OU_ADDR2"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="LE_ADDR3 !='' ">
            <xsl:value-of select="OU_ADDR3"/>
            <fo:block/>
        </xsl:if>
        <xsl:if test="OU_TOWN_CITY !=''">
            <xsl:value-of select="OU_TOWN_CITY"/>,
            <fo:leader leader-pattern="space" leader-length="2.0pt"/>
        </xsl:if>
        <xsl:value-of select="OU_REGION2"/>
        <fo:leader leader-pattern="space" leader-length="3.0pt"/>
        <xsl:value-of select="OU_POSTALCODE"/>
        <fo:block/>
        <xsl:value-of select="OU_COUNTRY"/>
    </xsl:otherwise>
</xsl:choose>

1 Ответ

35 голосов
/ 13 апреля 2011

Прежде всего, предоставленный длинный код :

    <xsl:choose>
        <xsl:when test="OU_NAME='OU_ADDR1'">   --comparing two elements coming from XML             
            <!--remove if  adrees already contain  operating unit name <xsl:value-of select="OU_NAME"/> <fo:block/>-->
            <xsl:if test="OU_ADDR1 !='' ">
                <xsl:value-of select="OU_ADDR1"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR2 !='' ">
                <xsl:value-of select="OU_ADDR2"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR3 !='' ">
                <xsl:value-of select="OU_ADDR3"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="OU_TOWN_CITY !=''">
                <xsl:value-of select="OU_TOWN_CITY"/>,
                <fo:leader leader-pattern="space" leader-length="2.0pt"/>
            </xsl:if>
            <xsl:value-of select="OU_REGION2"/>
            <fo:leader leader-pattern="space" leader-length="3.0pt"/>
            <xsl:value-of select="OU_POSTALCODE"/>
            <fo:block/>
            <xsl:value-of select="OU_COUNTRY"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="OU_NAME"/>
            <fo:block/>
            <xsl:if test="OU_ADDR1 !='' ">
                <xsl:value-of select="OU_ADDR1"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR2 !='' ">
                <xsl:value-of select="OU_ADDR2"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR3 !='' ">
                <xsl:value-of select="OU_ADDR3"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="OU_TOWN_CITY !=''">
                <xsl:value-of select="OU_TOWN_CITY"/>,
                <fo:leader leader-pattern="space" leader-length="2.0pt"/>
            </xsl:if>
            <xsl:value-of select="OU_REGION2"/>
            <fo:leader leader-pattern="space" leader-length="3.0pt"/>
            <xsl:value-of select="OU_POSTALCODE"/>
            <fo:block/>
            <xsl:value-of select="OU_COUNTRY"/>
        </xsl:otherwise>
    </xsl:choose>

эквивалентен этому, гораздо более короткому коду :

<xsl:if test="not(OU_NAME='OU_ADDR1)'">
              <xsl:value-of select="OU_NAME"/>
        </xsl:if>
            <xsl:if test="OU_ADDR1 !='' ">
                <xsl:value-of select="OU_ADDR1"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR2 !='' ">
                <xsl:value-of select="OU_ADDR2"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="LE_ADDR3 !='' ">
                <xsl:value-of select="OU_ADDR3"/>
                <fo:block/>
            </xsl:if>
            <xsl:if test="OU_TOWN_CITY !=''">
                <xsl:value-of select="OU_TOWN_CITY"/>,
                <fo:leader leader-pattern="space" leader-length="2.0pt"/>
            </xsl:if>
            <xsl:value-of select="OU_REGION2"/>
            <fo:leader leader-pattern="space" leader-length="3.0pt"/>
            <xsl:value-of select="OU_POSTALCODE"/>
            <fo:block/>
            <xsl:value-of select="OU_COUNTRY"/>

Теперь, на ваш вопрос:

как сравнить два элемента из xml в виде строки

В Xpath 1.0 строки можно сравнивать только дляравенство (или неравенство) с использованием оператора = и функции not() вместе с оператором =.

$str1 = $str2

оценивается как true() точно, когда строка $str1 равнастрока $str2.

not($str1 = $str2)

оценивается как true() точно, когда строка $str1 не равна строке $str2.

Существует также !=оператор.Этого, как правило, следует избегать, поскольку он имеет аномальное поведение всякий раз, когда один из его операндов является набором узлов.

Теперь правила для сравнения двух узлов элементов похожи :

$el1 = $el2

вычисляется до true() точно, когда строковое значение $el1 равно строковому значению $el2.

not($el1 = $el2)

оценивается до true() точно, когда строковое значение $el1 не равно строковому значению $el2.

Однако, если один из операндов = является набором узлов, тогда

 $ns = $str

оценивается как true() точно, когда есть хотя бы один узел в наборе узлов $ns1, чье строковое значение равно строке $str

$ns1 = $ns2

оценивается как true() точно, когда есть хотя быодин узел в наборе узлов $ns1, строковое значение которого равно строковому значению некоторого узла из $ns2

Следовательно, выражение :

OU_NAME='OU_ADDR1'

оценивается в true() только тогда, когда есть хотя бы один дочерний элемент текущего узла, который яс именем OU_NAME и строковым значением которого является строка 'OU_ADDR1'.

Это явно не то, что вы хотите!

Скорее всего, вы хотите:

OU_NAME=OU_ADDR1

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

Наконец, , в XPath 2.0 строки можно сравнивать также с использованием операторов сравнения значений lt, le, eq, gt, ge и унаследованного от XPath 1.0 общего оператора сравнения =.

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

...