5

When my tests are run with XSpec, there is a glaring problem: the base URI of global variables is set to the xspec parent that's running my XSLT and not the XML input itself.

Thus, when my XSL transformation is ran by itself against the XML, everything is fine and the global variables are selecting what they should: elements in the input XML.

However, when it is run via XSpec, the base URI is set to XSpec itself - presumably because the XSLT spec defines base URI as:

If an element or processing instruction occurs in an external entity, the base URI of that element or processing instruction is the URI of the external entity; otherwise, the base URI is the base URI of the document.

Which is a problem for me. I've tried using the xml:base attribute on both the variables and the xsl:stylesheet: but that did not seem to affect the base URI; it only affected fn:static-base-uri(). Also, static-base-uri() always returns the right URI I'd like - so I'd like that value to somehow become the base URI for my global variables.

Once I move the variables into a template and they become local, their base URI is fine. But that'll defeat the entire point of using variables for me, and that is not duplicating select calls.

Any tips on how to solve this?

I'm using XSLT 2.0 with SAXON EE 9.4.0.6 (& HE edition).


Update 1

I've done some more investigating, and it seems XSpec calls Saxon in this manner:

java -cp "%CP%" net.sf.saxon.Transform -o:%RESULT% -s:%XSPEC% -xsl:%TEST_STYLESHEET% -it:{http://www.jenitennison.com/xslt/xspec}main

Which means that -s, the source XML file, is the .xspec stylesheet itself. Makes sense if it has to supply some XML data for a transformation to work, but in this case it is the transformation itself that imports the XML data it works with via fn:doc() - and unfortunately within my xsl's global level, the base uri is wrong and not set to the imported document but to the xspec stylesheet.

So, as a test, I set the Saxon -s flag to the XML input document and tada - the base URI is now correct. But this means that I can't use any other xml within xspec and so isn't a very workable solution.


Update 2

Given some more feedback from Michael Kay (thanks!), I've attached the minimal test case I'm working with. You'll also want to download XSpec 0.4-rc1, but that's not necessary.

Once you've got XSpec, if you're on Windows, xspec-0.4.0rc1/bin/xspec.bat needs to be edited to point to the Saxon jar on line 3.

Otherwise, to run it, you do xspec.bat .\DCM2EA.xspec.

The base URI in global in the output will, ideally, point to NEHTA-00009-Adverse_Reaction-Structure (sample data).xml. Right now, it does not - it points to the .xspec. This is directly influenced by -s:%XSPEC% in xspec.bat on line 73.

The way xspec works is that it creates an intermediary transformation given DCM2EA.xspec and its own tests in xspec/DCM2EA.xsl and runs that transformation (that's why XSpec in this case is optional, you can run xspec - bad attribute name/xspec/DCM2EA.xsl directly).

The issue that I'm having is that base-uri() within the global context in the original DCM2EA.xsl is set to the xspec file, which is wrong. The base-uri() inside a template is set fine (as you see by Base URI now in the output), but it's impractical to move the variables to the local scope.

Specifying the input xml data isn't feasible either because my actual .xspec imports several different files, and I don't want to break up the 190 tests I've got and add such workarounds.

I was hoping that xml:base would help here, but I haven't gotten it to work and am out of solutions.

Thanks for looking!

potame
  • 7,597
  • 4
  • 26
  • 33
Vadim Peretokin
  • 2,221
  • 3
  • 29
  • 40
  • 2
    Your analysis of the situation is close, but not 100% accurate. When the value of a global variable is a temporary document, the base URI of that document is always the base URI of the stylesheet: that is, the same as static-base-uri(). I think we need to see some code, specifically, when you say "the base URI" is set to XSpec itself, we need to see which base URI you are talking about and how you are using it. – Michael Kay Aug 21 '13 at 08:50
  • In this case the temporary document is an actual .xsl that is generated and then run as a transformation (the process it managed by a shell script). That wasn't clear there, I apologize. I've attached the test case now and explained how I'm working with it, thanks for answering! – Vadim Peretokin Aug 21 '13 at 22:03

1 Answers1

1

Because of my constraints I'm not in a position to check your code or run tests, but your situation reminds me of a situation I had where I replaced the following:

<xsl:variable name="x" as="element()">
  <stuff>
    <more/>
  </stuff>
</xsl:variable>
....  select="$x" ...

with the following:

<xsl:variable name="x" as="element()">
  <wrapper xml:base="something">
    <stuff>
      <more/>
    </stuff>
  </wrapper>
</xsl:variable>
.... select="$x/*" ...

That way <stuff> has the base URI but without an xml:base= attribute, yet I'm selecting <stuff> in both situations. I think my issue was that I needed to set the base URI but the DTD validating the document didn't provide for the attribute ... or something along those lines since that doesn't sound quite right as I've written it.

I hope this helps.

G. Ken Holman
  • 4,333
  • 16
  • 14
  • Is the ```something``` in xml:base supposed to be anything special? I tried: ``` ``` Declared in the global context, but that still had it's context set to the original stylesheet invoking this child stylesheet, and not to the child stylesheets input XML. Woe! – Vadim Peretokin Sep 01 '13 at 22:25
  • No, nothing special. I was hoping the base URI would attach to the child elements. With more time today to understand your situation, I see really that my suggestion would not have helped. You appear to be losing the base URI along the way somewhere. Forgive me for not being able to help. – G. Ken Holman Sep 02 '13 at 01:37
  • No worries. Thanks. The base URI is only lost in the global context - it is fine within all of the templates. However, due to the way variables work in XSLT, I need my variables selecting nodes to be in the global context. Pity. – Vadim Peretokin Sep 02 '13 at 05:35