Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Nikhil Verma
Nikhil Verma

Posted on

     

XPaths in the modern age

XPaths are selectors you can use to query the elements in your document (HTML, XML etc). They are similar but complex and more featureful versions of CSS query selectors many are used to.

This is an example XPath which can find the Google Search button by starting from the search input. It's a roundabout way of doing this but it shows the powers of XPath over normal query selectors which can't do this.

$x(`//textarea/ancestor::form//input[@value="Google Search"]`);
Enter fullscreen modeExit fullscreen mode

XPath with Web components

Since XPath is a pretty old specification (created in 1999 and last updated in 2016). It doesn't specify how to operate with Web components and shadow DOM.

So if you want to write an XPath which selects an element inside the shadow DOM of a component you simply can't. The only solution is to find the component with the XPath. Then use theshadowRoot node to then further drill down into the component. For nested components it quickly becomes impractical.

To be fair this problem with shadow DOM is also present in querySelectors which don't work with it either. Lit has it'sown section dedicated to using custom@query decorators to find elements.


XPath with Vue 3

There is a very specific and peculiar problem that you face when using XPaths with Vue 3, which took me a long time to debug and find out.

Vue 3 when rendering child slots appends what's called "anchor" nodes to help it optimise it's updates. For example if you have a component like this:

<Text>   Hello World!</Text>
Enter fullscreen modeExit fullscreen mode

And you render it in Vue 3 like this.

<span><slot/><span>
Enter fullscreen modeExit fullscreen mode

What Vue 3 will do is output the following DOM structure

<span>    ""    "Hello World!"    ""</span>
Enter fullscreen modeExit fullscreen mode

Here"" is an empty text node. This trips up thecontains(text()) API of XPath. So if you were relying on your elements containing a specific text you won't be able to do that anymore.

Here is a Github issue with examples.vue/core/issues/8444


A workaround

To solve both of the problems above, I had to ponyfill XPath in our application.

There was an excellentxpath polyfill library which I forked and modified to add support for both Shadow DOM and Vue 3 text nodes.

This makes it "non spec" but it solves our needs and doesn't impact our development velocity.

It's published herexpath-next

import{parse}from'xpath-next';constexpression="//span";constcontextNode=document.body;constnodes=parse(expression).select({node:contextNode,isHtml:true});
Enter fullscreen modeExit fullscreen mode

My key takeaway from this experience is reliable technologies stop being so because the ecosystem moves on and makes them incompatible.

One could argue that Vue 3 behaviour should be fixed. But the fact that Web components don't work transparently with XPaths makes it hard to justify using it in it's original specification.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Joined

More fromNikhil Verma

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp