Skip to content

Instantly share code, notes, and snippets.

@eerohele
Last active May 27, 2016 21:19
Show Gist options
  • Save eerohele/d7329be21d4af076a1161a63c364fad1 to your computer and use it in GitHub Desktop.
Save eerohele/d7329be21d4af076a1161a63c364fad1 to your computer and use it in GitHub Desktop.
"Unit testing" XSLT with XQuery and Saxon
declare namespace saxon="http://saxon.sf.net/";
declare option saxon:output "method=xml";
declare option saxon:output "indent=yes";
declare option saxon:output "omit-xml-declaration=yes";
(: Requires Saxon-PE or Saxon-EE, unfortunately. :)
declare variable $stylesheet := local:prepare-stylesheet("test.xsl");
declare function local:prepare-stylesheet($stylesheet as xs:string) {
saxon:compile-stylesheet(doc($stylesheet))
};
declare function local:description($description as xs:string) as attribute(description)? {
if (normalize-space($description))
then attribute description { $description }
else ()
};
declare function local:assert($description as xs:string, $input as node(), $expected as node()) {
let $actual as node()* := saxon:transform($stylesheet, $input)/*
(: Could maybe write an extension function that calls XMLUnit 2 to produce a useful diff? :)
return if (not(deep-equal($actual, $expected)))
then
<error>
{ local:description($description) }
<input>{ $input }</input>
<expected>{ $expected }</expected>
<actual>{ $actual }</actual>
</error>
else
<ok>
{ local:description($description) }
</ok>
};
declare function local:assert($input as node(), $expected as node()) {
local:assert("", $input, $expected)
};
(:
Shame about having to wrap every local:assert call in braces. Is there any way
around that?
:)
(:
Output XML, or maybe HTML5? Or toggle via option? Colorized output for the
terminal would be optimal, but I don't think that's possible with XQuery?
:)
<result>
<!-- Optional description for test case. -->
{ local:assert("Paragraphs are converted.", <paragraph>foo</paragraph>, <p>foo</p>) }
<!-- Test case that fails. -->
{ local:assert(<paragraph>foo</paragraph>, <nope>foo</nope>) }
<!-- Test case that succeeds. -->
{ local:assert("@foo is converted.", <paragraph foo="bar"/>, <p bar="foo"/>) }
</result>
<result>
<!-- Optional description for test case. -->
<ok description="Paragraphs are converted."/>
<!-- Test case that fails. -->
<error>
<input>
<paragraph>foo</paragraph>
</input>
<expected>
<nope>foo</nope>
</expected>
<actual>
<p>foo</p>
</actual>
</error>
<!-- Test case that succeeds. -->
<ok description="@foo is converted."/>
</result>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="paragraph">
<p>
<xsl:apply-templates select="@* | node()"/>
</p>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@foo">
<xsl:attribute name="bar" select="'foo'"/>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment