I think the reason that Expression.getSystemId() doesn't use the location map is because of problems encountered with XSLT packages. The problem here is generating globally-unique location IDs when packages are compiled indepedently. In fact this problem was never quite solved for 9.6, which continues to use globally-unique location IDs because they are needed on the receiver pipeline. But the change was an attempt to reduce reliance on them.
I'm trying to see if I can make it work using the system ID of the container, making sure this is correctly set. First step is to change XQueryExpression.getSystemId() to return mainModule.getSystemId() instead of null.
This now gives me a system ID but unfortunately it is wrong. In my test case, the failure occurs in a function in an imported module, but the function was inlined, and I'm now getting the original line number, but the system ID of the module into which the code was inlined. Because the inlined function code doesn't have a container of its own, this suggests that using the system ID of the container is not safe, so we may have to fall back on location IDs after all.
I have changed Expression.getSystemId() to use the locationId and locationMap. This change gives correct location information both for my dynamic error test case and for the original TraceListener test case. I now need to check that it doesn't cause regression elsewhere.
Checked OK that static errors in XQuery are still reported correctly: both in the main module and library modules. Also ran the "error" test-set for XSLT 3.0 and checked that module and line information is being produced. Also checked -T output with both Transform and Query command line. All seems well, so I will commit the changes for both th 9.6 nad 9.7 branches.