XML search (XPATH / XSLT) returns the path in terms of 'rank'

I want to search for XML and return the return search number. For instance; looking for the “orange” in the following list, I want to go back.

<fruits>
<name>apple</name>
<name>apple</name>
<name>apple</name>
<name>apple</name>
<name>apple</name>
<name>orange</name>
<name>apple</name>
<name>apple</name>
<name>apple</name>
</fruits>

I am trying to create XPATH as:

/fruits/name[6]

And I need this position number to be calculated at the input.

( /fruits/name[$position]where $positionis the calculated value of this orange among apples there).

I think some kind of recursive pattern (walking backwards from a search hit?) Can do this - but I'm trying my best to do it; and maybe there is another way?

+3
source share
3 answers

This style sheet:

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

    <xsl:template match="/">
        <xsl:variable name="position">
            <xsl:apply-templates select="fruits/name"/>
        </xsl:variable>

        <result><xsl:value-of select="$position"/></result>
    </xsl:template>

    <xsl:template match="name">
        <xsl:if test="text() = 'orange'">
            <xsl:value-of select="position()"/>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

$position, (, , , ):

<result>6</result>
+1

name :

count(/fruits/name[.='orange']/preceding-sibling::name) + 1

, ( ), :

/fruits/name[.='orange']

, , .

+1

, , . , . , XPath .

XML

<fruits>
    <name>apple</name>
    <name>apple</name>
    <name>apple</name>
    <name>apple</name>
    <name>apple</name>
    <name>orange</name>
    <name>apple</name>
    <name>apple</name>
    <name>apple</name>
</fruits>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="search-string" select="'orange'"/>

    <xsl:template match="/">
        <xsl:apply-templates select="//*[contains(text(),$search-string)]"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
            <!--Predicate is only output when needed.-->
            <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>  
    </xsl:template>

</xsl:stylesheet>

/fruits/name[6]

If the search bar was "apple", it will return the path for each item namewith an "apple" in it. If you do not need all these paths, you can return either the first or the last by changing xsl:apply-templates...

First

<xsl:apply-templates select="(//*[contains(text(),$search-string)])[1]"/>

Last

<xsl:apply-templates select="(//*[contains(text(),$search-string)])[last()]"/>
+1
source

All Articles