That's not the fault of the XML community at large, but just a lack of resources for the implementation of an unpaid open source project.
You can happily use XPath 3.1 with Saxon, BaseX, eXist. All three use Java, so, it's not portable, but Saxon has a C library, that mirrors the Java version 1:1, and that C library is also available as open source, though, it lacks some XPath 3.x features, like higher order functions, then.
For the command line, there is a partial XPath 3.1 implementation with 'xidel'.
But I agree, libxml and libxslt being at XPath 1.0 for so long, did not serve XML well.
The fragmentation you mentioned is part of what made this so frustrating: if everything you used was within certain toolchains, the experience was fairly good but then you'd need to use a different ecosystem and either drop back to good old XPath 1 or take on more technical debt. In many cases, the answer I saw people favor was leaving the XML world as quickly as possible, which is something the community has a strong interest in.
1. For example, Saxon added support for Python just a few days ago: https://www.saxonica.com/saxon-c/release-notes.xml Imagine if that had happened a decade ago and everyone who was stuck with libxml2 could have easily switched?
On a fair note, one should also take into account, that Saxonica is a rather small, even if highly skilled, shop and the program, they create, is a huge undertaking.
JSON is a better data language, but a lot of that can be laid at the feet of XSD and the big squandering of momentum it represented.
Handling namespaces correctly requires that the parser API be changed in non-backwards-compatible ways. This would have broken every single piece of code that used an XML parser. So instead, people mangled documents by simply flattening all the namespaces together if you tried using the old API.
This was a godawful nightmare and made everybody who was around at the time absolutely hate XML namespaces -- even those of us who know why they are so important. Plus namespaces are not exactly an "ELI5" topic, so a lot of lazy programmers looked at this and said "that's complicated, I don't want to learn it, HEY LOOK there's this older deprecated API that doesn't have them -- I'll use that!" So the old APIs became immortal and in fact gained additional users long after they were deprecated.
They should never have let the 1.0 standard out the door without namespaces in it.
1. User gets a simple XML file and writes XPath, XSLT, or other code which says `/foo/bar`, which fails.
2. User notices that while it's written as `<foo><bar>` in the source, it's namespaced globally so they change code to use `/ns:foo/ns:bar`, which also fails.
3. User does more reading and realizes it needs to be `/{http://pointless/repetition}foo/{http://pointless/repetition... or something like repeating the document-level namespace definitions on every call so their `ns:foo` is actually translated rather than treated as some random new declaration.
4. User does something hacky with regular expression to get the job done and at the next chance ports everything to JSON instead, seeing 1+ orders of magnitude better performance and code size reductions even though it's technically less correct.
That experience would have been much less frustrating if you could rely on tools implementing the default namespace or being smart enough to allow you to use the same abbreviations present in the document so `<myns:foo>` could be referenced everywhere you cared about it as `myns:foo` with the computer doing the lookup rather than forcing the developer to do it manually.