xspec: Indentation differences make test failed since 1.3.0

Hi,

I often use href attribute to refer external files in my XSpec tests. While moving from 1.0.9 to 1.3.0 (and furher versions to 1.6.0) most of my tests move from success to failed. I tried to understand why and it looks like this is an indentation problem.

I made a simple test with an XSL adding a wrapper element around <body> element. It uses xspec maven plugin to launch the tests, the XSpec version can be changed within the pom.xml Here is a zip to test: xspec-indentation-problem.zip

  • Setting XSpec version to 1.0.9: build is OK, every tests success
  • Setting XSpec version to 1.3.0: build is KO, Test 1 succeed and Test 2 failed.

Test 1 and 2 are the same except that test 2 refers an indented file:

    <x:scenario label="Test 1 : expect in file">
      <x:context href="xml.xml" />
      <x:expect label="expect" select="/*" test="/*"  href="xml.result.xml"/>
    </x:scenario>
    
    <x:scenario label="Test 2 : expect in file - indented">
      <x:context href="xml.xml" />
      <x:expect label="expect" select="/*" test="/*"  href="xml.result.indent.xml"/>
    </x:scenario>

I select and test “/*” to avoid serialisation differences such as xml PI. Here the XSLT serialisation is set to “xml” (and not indented, by default) such as the default serialisation used in XSpec I guess. I generated xml.result.xml by applying the XSLT to the input file xml.xml. The test off course succeed here. I copied its content and indent it into xml.result.indent.xml and here the test failed from XSpec version 1.3.0.

In Test 3 I started trying the solution proposed in issues #227, which didn’t work at this point. Test 4 is the same as Test 2 but the content is in the XSpec file itself, indented : it works.

Any Ideas what could have changed from Xspec version 1.3.0 in the comparaison algo?

Thanks in advanced, Matthieu

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 24 (11 by maintainers)

Commits related to this issue

Most upvoted comments

There are three ways of describing expectations in x:expect. Two of them are related to @test. I’ve made a major rewrite in the “Expectations” section of Wiki based on that.

I think x:expect (particularly its @test) shouldn’t have been designed in its current form, but unfortunately it’s been there for more than 10 years and changing its spec today is difficult. Hopefully, simplifying x:expect (with breaking compatibility) will be attempted in v3.0.

select="doc() sounds like a handy workaround. The base URI of each element is not kept in the compiled stylesheet/query. (And I don’t know how to keep it in the compiled query.) That’s usually fine, because @href is resolved as absolute in the compiled stylesheet/query. For your use case, a global variable $x:xspec-uri is available at run time. It holds the absolute URI (already resolved by the catalog if any) of the XSpec file (the root XSpec file if x:import is involved). So you can usually write <x:expect select="'relative/path/from/root-xspec-file' => resolve-uri($x:xspec-uri) => doc()">.

Thank you for these explanations @AirQuick !

The idea of the utility function x:delete-patterns() looks really nice and would allow precise customization. Maybe I could solve my white-space issue using this kind of pattern: text()[matches(normalize-space(.), '\p{Z}')] to ignore white-space only text nodes 😃

#364 made changes in comparing the actual result and the expected result.

Ok that’s clear, thank you for this reminder.

I understand the rule “XSpec won’t modify the content of @href”, it’s true it is usefull to be confident with this, especially with other features like AVT, TVT, uri, as you said.

Isn’t there no way to specify the comparison algorithm, without changing this rule?

About my proposition, there is something I’m not quite clear with. You said:

@xml:space="default" has no effect unless you use it in a descendant of @xml:space="preserve"

Yes, this is xml:space spec I guess. But on the other hand you said:

Whitespace-only text nodes in the content of @href are always preserved

I think I have (miss?)interpreted this last rule as “the default value for @xml:space is preserved when using @href” So if we want to change it we have to set it explicitely to default (opposite of preserve). Althought this is a bit strange to use default to override the default preserve value 😃

I think I would have prefer xml:space default value to be default even when using href attribute, but this would break the rule “XSpec won’t modify the content of @href” as far as I understand.

By the way, writing this comment gives me the idea to test :

<x:scenario label="Test 9 : context/expect uses fn:doc function instead of href">
  <x:context select="doc('../../samples/xml.xml')"/>
  <x:expect label="expect" 
    select="doc('../../samples/xml.result.indent.xml')/*" 
    test="doc('../../samples/xml.result.indent.xml')/*"/>
</x:scenario>

And it works fine 😃 As long as I don’t use href attribute, white-space only text nodes are ignored in the diff as expected. The drawback of this solution is about the uri of the files which are string here:

  • they don’t heritate xml:base attribute (which I often use in XSpec file so I don’t have to repeat the test files folder in each test)
  • I have to add an extra '../' because the context folder is the xspec folder created on the fly by the current xspec implementation. Meaning my uri is tied to the implementation.

I tried to get it right using resolve-uri:

<x:scenario label="Indentation tests" xml:base="../samples/">
  <x:variable name="base-uri" select="base-uri()"/>
  <x:scenario label="Test 10 : context/expect uses fn:doc function instead of href with resolve-uri">
    <x:context select="doc(resolve-uri('xml.xml', $base-uri))"/>
    <x:expect label="expect" 
      select="doc(resolve-uri('xml.result.indent.xml', $base-uri))/*" 
      test="doc(resolve-uri('xml.result.indent.xml', $base-uri))/*"/>
  </x:scenario>
</x:scenario>

But I get a path error (file unfound). Looks like the variable $base-uri contains the xspec implementation folder and not the folder specified in xml:base. Should I raise a bug for this? By the way static-base-uri() also give the compiled xspec uri and not the original xspec file uri, should it?

I also have problems with xspec-maven-plugin (using last XSpec 1.6.0) and uri on test 8 and 9 which work well with Oxygen 22.1. This has maybe something to do with https://github.com/xspec/xspec-maven-plugin-1/issues/58, @cmarchand?

Last zip : xspec-indentation-problem.20200729.zip

  • We’ve seen multiple cases where the user does not like the deliberate nature of x:*/@href.
  • XInclude has its draw back:
    • @xml:base contamination (from the point of view of our use cases)
    • Supporting XInclude both in CLI and Ant costs some tests and implementation.

So I’m considering implementing a new element x:include (not xi:include) which would work like this:

With this external XML file (file.xml),

<e/>

an XSpec file

<x:expect>
  <foo>
    <x:include href="file1.xml" />
  </foo>
</x:expect>

is considered equivalent to

<x:expect>
  <foo>
    <e/>
  </foo>
</x:expect>

which means:

  • The base URI of the included documents is not propagated to the included nodes.
  • All the nodes (including @xml:base and namespaces) within the included documents are not modified.
  • Whitespace-only text nodes, attribute value templates, text value templates are handled as if they were written directly in the XSpec file.

What do you think?