0

I am trying to search for an element and return the full xpath to that element in XSLT.

For example, I have an XSLT file like this:

<title>
  <header>
    <info1>A</info1>
    <info2>B</info2>
  </header>
</title>

I'm looking for a function where I can parse the XSLT file, enter something like:

info1

and return:

title/header/info1

If there is more than one element with that tag, then I want to return all of them.

I've tried the methods suggested here and here but they don't seem to work. Any help would be appreciated, thanks!

6
  • It seems that the example you've chosen are attribute based (condition starting with @). Try without the @. Commented Dec 14, 2020 at 16:55
  • I used this XPath tester and achieved to isolate the node with: //*[text()="A"]. After that you have to rebuild the path from this node until the root (but in reverse) by getting the parent of each node until you reach the root. Commented Dec 14, 2020 at 16:58
  • I found that XPath tester as well! Unfortunately, my goal here is to automate the process of rebuilding the path from element to root, rather than manually going element by element. Commented Dec 14, 2020 at 17:04
  • By automate you mean in your Python script? You can do it recursively. Commented Dec 14, 2020 at 17:06
  • 1
    Please explain why the answers to the linked questions "don't seem to work". Commented Dec 14, 2020 at 18:18

2 Answers 2

2

Using lxml

from lxml import etree

xml = '''<title>
  <header>
    <info1>A</info1>
    <info2>B</info2>
    <jack>
        <info1>AA</info1>
    </jack>
  </header>
</title>'''

root = etree.fromstring(xml)
tree = etree.ElementTree(root)
elements = root.findall('.//info1')
for e in elements:
    print(tree.getpath(e))

output

/title/header/info1
/title/header/jack/info1
Sign up to request clarification or add additional context in comments.

Comments

1

If you want to do this through XSLT, try something like:

XSLT 1.0

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

<xsl:param name="element-name">info1</xsl:param>

<xsl:template match="/">
    <xsl:for-each select="//*[name()=$element-name]">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="name()"/>
            <xsl:if test="position() != last()">
                <xsl:text>/</xsl:text>
            </xsl:if>
        </xsl:for-each>    
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>   
</xsl:template>

</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.