Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Removing comments from expected XML before testing #1579

Open
sawprogramming opened this issue Dec 8, 2021 · 2 comments
Open
Labels

Comments

@sawprogramming
Copy link

sawprogramming commented Dec 8, 2021

Hello,

Is it possible to remove comments nodes from the expected XML file before doing the comparison test? All of my files to test with x:expect are examples containing detailed comments that explain each element in the target XML. These comments are useful for those writing stylesheets to create the same output, as they help identify the elements in the source XML that should be mapped to them. For example, one expected XML file will look like:

<Foo>
    <!-- BAR - The Bar element holds important text greeting the world. Required. -->
    <Bar>Hello world!</Bar>

    <!-- ******************************************************************************** -->
    <!-- BAZ - An optional element that holds a greeting to the moon.                     -->
    <!-- ******************************************************************************** -->
    <Baz>Hello moon!<!-- Note that this greets the moon, not the world. --></Baz>
</Foo>

My XSpec definition is something along the lines of:

<x:description xmlns:x="http://www.jenitennison.com/xslt/xspec"
               stylesheet="FooBar.xslt">

    <x:scenario label="FooBar: Greetings for the earth and moon">
        <x:context href="FooBarInput.xml?strip-space=yes"/>

        <x:expect label="The output transformation matches the expected output."
                  href="FooBarExpected.xml?strip-space=yes"
                  test="/*"
                  select="/*"/>
    </x:scenario>

</x:description>

And the output of my stylesheet against the input is something along the lines of:

<Foo>
    <Bar>Hello world!</Bar>
    <Baz>Hello moon!</Baz>
</Foo>

Comparing my output to the expected output using the XSpec definition from above results in test failures because of the comment nodes. I would prefer to leave the comments in my expected XML files because of their usefulness to developers, but I don't want the comments to be considered required when the test is run.

Screen Shot 2021-12-08 at 10 18 34 AM

@sawprogramming
Copy link
Author

sawprogramming commented Dec 9, 2021

I tinkered with the compilation stylesheets a little and came up with a hack that removes comments from both the result and the expected result before comparing them. So far, it has worked without any issues. Here is the diff:

Index: xspec/src/compiler/xslt/declare-variable/declare-variable.xsl
===================================================================
--- xspec/src/compiler/xslt/declare-variable/declare-variable.xsl	(revision 41988)
+++ xspec/src/compiler/xslt/declare-variable/declare-variable.xsl	(working copy)
@@ -43,8 +43,17 @@
                </xsl:otherwise>
             </xsl:choose>
          </xsl:element>
+
+         <xsl:element name="xsl:variable" namespace="{$x:xsl-namespace}">
+            <xsl:attribute name="name"><xsl:value-of select="$temp-doc-uqname"/>-rc</xsl:attribute>
+            <xsl:element name="xsl:apply-templates" namespace="{$x:xsl-namespace}">
+               <xsl:attribute name="select">$<xsl:value-of select="$temp-doc-uqname"/></xsl:attribute>
+               <xsl:attribute name="mode">remove-comments</xsl:attribute>
+            </xsl:element>
+         </xsl:element>
       </xsl:if>
 
+
       <xsl:element name="xsl:{if ($as-param) then 'param' else 'variable'}"
          namespace="{$x:xsl-namespace}">
          <!-- @as or @select may use namespace prefixes. @select may use the default namespace such
@@ -61,7 +70,7 @@
                <xsl:variable name="selection" as="xs:string"
                   select="(@select, '.'[current()/@href], 'node()')[1]" />
                <xsl:attribute name="select">
-                  <xsl:text expand-text="yes">${$temp-doc-uqname} ! ( {$selection} )</xsl:text>
+                  <xsl:text expand-text="yes">${$temp-doc-uqname}-rc ! ( {$selection} )</xsl:text>
                </xsl:attribute>
             </xsl:when>

Index: xspec/src/compiler/xslt/main.xsl
===================================================================
--- xspec/src/compiler/xslt/main.xsl	(revision 42002)
+++ xspec/src/compiler/xslt/main.xsl	(working copy)
@@ -111,6 +111,23 @@
             </xsl:if>
          </xsl:if>
 
+         <!-- The templates to remove comments from results and expected results before comparing them. -->
+         <xsl:element name="xsl:template" namespace="{$x:xsl-namespace}">
+            <xsl:attribute name="match">@*|element()|text()|processing-instruction()</xsl:attribute>
+            <xsl:attribute name="mode">remove-comments</xsl:attribute>
+            <xsl:element name="xsl:copy" namespace="{$x:xsl-namespace}">
+               <xsl:element name="xsl:apply-templates" namespace="{$x:xsl-namespace}">
+                  <xsl:attribute name="select">@*|node()</xsl:attribute>
+                  <xsl:attribute name="mode">remove-comments</xsl:attribute>
+               </xsl:element>
+            </xsl:element>
+         </xsl:element>
+
+         <xsl:element name="xsl:template" namespace="{$x:xsl-namespace}">
+            <xsl:attribute name="match">comment()</xsl:attribute>
+            <xsl:attribute name="mode">remove-comments</xsl:attribute>
+         </xsl:element>
+
          <!-- The main compiled template. -->
          <xsl:comment> the main template to run the suite </xsl:comment>
          <xsl:element name="xsl:template" namespace="{$x:xsl-namespace}">

This added the below templates to the compiled stylesheet...

<xsl:template match="@*|node()" mode="remove-comments">
   <xsl:copy>
      <xsl:apply-templates select="@*|node()" mode="remove-comments"/>
   </xsl:copy>
</xsl:template>

<xsl:template match="comment()" mode="remove-comments"/>

... and changed the following section of the compiled scenario/expect from ...

<xsl:variable name="Q{urn:x-xspec:compile:impl}context-d57e0-doc"
              as="document-node()"
              select="doc('file:/path/to/the/FooBarInput.xml?strip-space=yes')"/>
<xsl:variable name="Q{urn:x-xspec:compile:impl}context-d57e0"
              select="$Q{urn:x-xspec:compile:impl}context-d57e0-doc ! ( . )"/>

... to ...

<xsl:variable name="Q{urn:x-xspec:compile:impl}context-d57e0-doc"
              as="document-node()"
              select="doc('file:/path/to/the/FooBarInput.xml?strip-space=yes')"/>
<xsl:variable name="Q{urn:x-xspec:compile:impl}context-d57e0-doc-rc">
   <xsl:apply-templates select="$Q{urn:x-xspec:compile:impl}context-d57e0-doc"
                        mode="remove-comments"/>
</xsl:variable>
<xsl:variable name="Q{urn:x-xspec:compile:impl}context-d57e0"
              select="$Q{urn:x-xspec:compile:impl}context-d57e0-doc-rc ! ( . )"/>

... which applies my templates to remove comments from the input document, stores it in a new variable, then makes the final context variable reference the version of the document without comments instead of the version with comments.


I'm still open to better solutions!

@galtm
Copy link
Collaborator

galtm commented May 8, 2022

Hi @sawprogramming ,

Are you aware of the ability to incorporate your own helper functions into the XSpec testing process? Please see Integrating Your Own Test Helpers. There is also a set of tutorial files about removing whitespace-only text nodes using a test helper, and your question about removing comments seems similar. If the test helper approach works for you, then you won't need to modify the XSpec compiler locally.

@galtm galtm added the question label Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants