Imported Upstream version 0.17
authorIan Beckwith <ianb@erislabs.net>
Sat, 19 Oct 2013 22:26:23 +0000 (23:26 +0100)
committerIan Beckwith <ianb@erislabs.net>
Sat, 19 Oct 2013 22:26:23 +0000 (23:26 +0100)
12 files changed:
Changes
MANIFEST
META.yml
MYMETA.json [deleted file]
MYMETA.yml [deleted file]
README
lib/URI/Template.pm
t/12-suite.t
t/cases/extended-tests.json
t/cases/json2xml.xslt [new file with mode: 0644]
t/cases/negative-tests.json
t/cases/transform-json-tests.xslt [new file with mode: 0644]

diff --git a/Changes b/Changes
index 8c5b03e..a9677c3 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 Revision history for Perl extension URI::Template
 
+0.17 2013-03-11
+ - Special case return from empty hash and array values in query strings
+
 0.16 2012-05-30
  - Conform to latest spec RFC 6570 (RT 66651)
  - Re-use test suite from official github repo
index c09cc13..3f58770 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -11,8 +11,6 @@ lib/URI/Template.pm
 Makefile.PL
 MANIFEST                       This list of files
 META.yml
-MYMETA.json
-MYMETA.yml
 README
 t/01-use.t
 t/10-basic.t
@@ -20,6 +18,8 @@ t/12-suite.t
 t/98-pod.t
 t/99-podcoverage.t
 t/cases/extended-tests.json
+t/cases/json2xml.xslt
 t/cases/negative-tests.json
 t/cases/spec-examples-by-section.json
 t/cases/spec-examples.json
+t/cases/transform-json-tests.xslt
index e9316a4..fc3f038 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -27,4 +27,4 @@ requires:
 resources:
   license: http://dev.perl.org/licenses/
   repository: http://github.com/bricas/uri-template
-version: 0.16
+version: 0.17
diff --git a/MYMETA.json b/MYMETA.json
deleted file mode 100644 (file)
index d3a923f..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-   "abstract" : "Object for handling URI templates (RFC 6570)",
-   "author" : [
-      "=over 4"
-   ],
-   "dynamic_config" : 0,
-   "generated_by" : "Module::Install version 1.06, CPAN::Meta::Converter version 2.120921",
-   "license" : [
-      "perl_5"
-   ],
-   "meta-spec" : {
-      "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
-      "version" : "2"
-   },
-   "name" : "URI-Template",
-   "no_index" : {
-      "directory" : [
-         "inc",
-         "t"
-      ]
-   },
-   "prereqs" : {
-      "build" : {
-         "requires" : {
-            "ExtUtils::MakeMaker" : "6.59",
-            "Test::More" : "0"
-         }
-      },
-      "configure" : {
-         "requires" : {
-            "ExtUtils::MakeMaker" : "6.59"
-         }
-      },
-      "runtime" : {
-         "requires" : {
-            "URI" : "0",
-            "URI::Escape" : "0",
-            "Unicode::Normalize" : "0",
-            "perl" : "5.006"
-         }
-      }
-   },
-   "release_status" : "stable",
-   "resources" : {
-      "license" : [
-         "http://dev.perl.org/licenses/"
-      ],
-      "repository" : {
-         "url" : "http://github.com/bricas/uri-template"
-      }
-   },
-   "version" : "0.16"
-}
diff --git a/MYMETA.yml b/MYMETA.yml
deleted file mode 100644 (file)
index 8874d8b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
----
-abstract: 'Object for handling URI templates (RFC 6570)'
-author:
-  - '=over 4'
-build_requires:
-  ExtUtils::MakeMaker: 6.59
-  Test::More: 0
-configure_requires:
-  ExtUtils::MakeMaker: 6.59
-dynamic_config: 0
-generated_by: 'Module::Install version 1.06, CPAN::Meta::Converter version 2.120921'
-license: perl
-meta-spec:
-  url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
-name: URI-Template
-no_index:
-  directory:
-    - inc
-    - t
-requires:
-  URI: 0
-  URI::Escape: 0
-  Unicode::Normalize: 0
-  perl: 5.006
-resources:
-  license: http://dev.perl.org/licenses/
-  repository: http://github.com/bricas/uri-template
-version: 0.16
diff --git a/README b/README
index 6de3191..0010981 100644 (file)
--- a/README
+++ b/README
@@ -49,7 +49,7 @@ AUTHORS
     *   Ricardo SIGNES <rjbs@cpan.org>
 
 COPYRIGHT AND LICENSE
-    Copyright 2007-2012 by Brian Cassidy
+    Copyright 2007-2013 by Brian Cassidy
 
     This library is free software; you can redistribute it and/or modify it
     under the same terms as Perl itself.
index 79c944f..390f6a6 100644 (file)
@@ -3,7 +3,7 @@ package URI::Template;
 use strict;
 use warnings;
 
-our $VERSION = '0.16';
+our $VERSION = '0.17';
 
 use URI;
 use URI::Escape        ();
@@ -123,7 +123,10 @@ sub _tostring_query {
     $join = '&' if $exp->{ op } =~ /[?&]/;
 
     if ( ref $value eq 'ARRAY' ) {
-        return unless @$value;
+        if( !@$value ) {
+            return if $var->{ explode };
+            return $var->{ name } . '=';
+        }
         if ( $var->{ explode } ) {
             return join( $join,
                 map { $var->{ name } . '=' . _quote( $_, $safe ) } @$value );
@@ -134,7 +137,10 @@ sub _tostring_query {
         }
     }
     elsif ( ref $value eq 'HASH' ) {
-        return unless keys %$value;
+        if( !keys %$value ) {
+            return if $var->{ explode };
+            return $var->{ name } . '=';
+        }
         if ( $var->{ explode } ) {
             return join(
                 $join,
@@ -387,7 +393,7 @@ URI object.
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2007-2012 by Brian Cassidy
+Copyright 2007-2013 by Brian Cassidy
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself. 
index cbe2869..3a763be 100644 (file)
@@ -7,6 +7,10 @@ use Scalar::Util ();
 BEGIN {
     eval "use JSON ();";
     plan skip_all => "JSON required" if $@;
+
+    eval { JSON->VERSION( 2 ) };
+    plan skip_all => "JSON version 2 of greater required" if $@;
+
     plan( 'no_plan' );
     use_ok( 'URI::Template' );
 }
@@ -23,8 +27,7 @@ for my $file ( @files ) {
     my $data = do { local $/; <$json> };
     close( $json );
 
-    eval { JSON->VERSION( 2 ) };
-    my $suite = $@ ? JSON::jsonToObj( $data ) : JSON::from_json( $data );
+    my $suite = JSON->new->utf8( 1 )->decode( $data );
 
     for my $name ( sort keys %$suite ) {
         my $info  = $suite->{ $name };
index ab6dc4c..959840e 100644 (file)
             "geocode"      : ["37.76","-122.427"],
             "first_name"   : "John",
             "last.name"    : "Doe", 
-            "Some%20Thing" : "foo"
+            "Some%20Thing" : "foo",
+            "number"       : 6,
+            "long"         : 37.76,
+            "lat"          : -122.427,
+            "group_id"     : "12345",
+            "query"        : "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }",
+            "uri"          : "http://example.org/?uri=http%3A%2F%2Fexample.org%2F",
+            "word"         : "drücken",
+            "Stra%C3%9Fe"  : "Grüner Weg",
+            "random"       : "šö䟜ñꀣ¥‡ÑÒÓÔÕÖ×ØÙÚàáâãäåæçÿ",
+            "assoc_special_chars"  :
+              { "šö䟜ñꀣ¥‡ÑÒÓÔÕ" : "Ö×ØÙÚàáâãäåæçÿ" }
         },
         "testcases":[
 
                [ "/search.json?q=URI%20Templates&geocode=37.76,-122.427&lang=en&page=5",
                  "/search.json?q=URI%20Templates&geocode=-122.427,37.76&lang=en&page=5"]
                 ],
-            ["/test{/Some%20Thing}", "/test/foo" ]
+            ["/test{/Some%20Thing}", "/test/foo" ],
+            ["/set{?number}", "/set?number=6"],
+            ["/loc{?long,lat}" , "/loc?long=37.76&lat=-122.427"],
+            ["/base{/group_id,first_name}/pages{/page,lang}{?format,q}","/base/12345/John/pages/5/en?format=json&q=URI%20Templates"],
+            ["/sparql{?query}", "/sparql?query=PREFIX%20dc%3A%20%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%3E%20SELECT%20%3Fbook%20%3Fwho%20WHERE%20%7B%20%3Fbook%20dc%3Acreator%20%3Fwho%20%7D"],
+            ["/go{?uri}", "/go?uri=http%3A%2F%2Fexample.org%2F%3Furi%3Dhttp%253A%252F%252Fexample.org%252F"],
+            ["/service{?word}", "/service?word=dr%C3%BCcken"],
+            ["/lookup{?Stra%C3%9Fe}", "/lookup?Stra%C3%9Fe=Gr%C3%BCner%20Weg"],
+            ["{random}" , "%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF"],
+            ["{?assoc_special_chars*}", "?%C5%A1%C3%B6%C3%A4%C5%B8%C5%93%C3%B1%C3%AA%E2%82%AC%C2%A3%C2%A5%E2%80%A1%C3%91%C3%92%C3%93%C3%94%C3%95=%C3%96%C3%97%C3%98%C3%99%C3%9A%C3%A0%C3%A1%C3%A2%C3%A3%C3%A4%C3%A5%C3%A6%C3%A7%C3%BF"]
         ]
     },
     "Additional Examples 2":{
                "/albums/person?fields=name,id,picture&token=12345"]
                ]
         ]
+    },
+    "Additional Examples 3: Empty Variables":{
+        "variables" : {
+            "empty_list" : [],
+            "empty_assoc" : {}
+        },
+        "testcases":[
+            [ "{/empty_list}", [ "" ] ],
+            [ "{/empty_list*}", [ "" ] ],
+            [ "{?empty_list}", [ "?empty_list="] ],
+            [ "{?empty_list*}", [ "" ] ],
+            [ "{?empty_assoc}", [ "?empty_assoc=" ] ],
+            [ "{?empty_assoc*}", [ "" ] ]
+        ]
+    },
+    "Additional Examples 4: Numeric Keys":{
+        "variables" : {
+            "42" : "The Answer to the Ultimate Question of Life, the Universe, and Everything",
+            "1337" : ["leet", "as","it", "can","be"],
+            "german" : {
+                "11": "elf",
+                "12": "zwölf"
+            }
+        },
+        "testcases":[
+            [ "{42}", "The%20Answer%20to%20the%20Ultimate%20Question%20of%20Life%2C%20the%20Universe%2C%20and%20Everything"],
+            [ "{?42}", "?42=The%20Answer%20to%20the%20Ultimate%20Question%20of%20Life%2C%20the%20Universe%2C%20and%20Everything"],
+            [ "{1337}", "leet,as,it,can,be"],
+            [ "{?1337*}", "?1337=leet&1337=as&1337=it&1337=can&1337=be"],
+            [ "{?german*}", [ "?11=elf&12=zw%C3%B6lf", "?12=zw%C3%B6lf&11=elf"] ]
+        ]
     }
 }
diff --git a/t/cases/json2xml.xslt b/t/cases/json2xml.xslt
new file mode 100644 (file)
index 0000000..59b3548
--- /dev/null
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Downloaded on 12/6/2012 from http://www.gerixsoft.com/blog/xslt/json2xml -->
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+       <xsl:template match="json">
+               <xsl:copy>
+                       <xsl:copy-of select="@*"/>
+                       <xsl:call-template name="json2xml">
+                               <xsl:with-param name="text" select="."/>
+                       </xsl:call-template>
+               </xsl:copy>
+       </xsl:template>
+
+       <xsl:template name="json2xml">
+               <xsl:param name="text"/>
+               <xsl:variable name="mode0">
+                       <xsl:variable name="regexps" select="'//(.*?)\n', '/\*(.*?)\*/', '(''|&quot;)(([^\\]|\\[\\&quot;''/btnvfr])*?)\3', '(-?\d+(\.\d+([eE][+-]?\d+)?|[eE][+-]?\d+))', '(-?[1-9]\d*)', '(-?0[0-7]+)', '(-?0x[0-9a-fA-F]+)', '([:,\{\}\[\]])', '(true|false)', '(null)'"/>
+                       <xsl:analyze-string select="$text" regex="{string-join($regexps,'|')}" flags="s">
+                               <xsl:matching-substring>
+                                       <xsl:choose>
+                                               <!-- single line comment -->
+                                               <xsl:when test="regex-group(1)">
+                                                       <xsl:comment>
+                                                               <xsl:value-of select="regex-group(1)"/>
+                                                       </xsl:comment>
+                                                       <xsl:text>&#10;</xsl:text>
+                                               </xsl:when>
+                                               <!-- multi line comment -->
+                                               <xsl:when test="regex-group(2)">
+                                                       <xsl:comment>
+                                                               <xsl:value-of select="regex-group(2)"/>
+                                                       </xsl:comment>
+                                               </xsl:when>
+                                               <!-- string -->
+                                               <xsl:when test="regex-group(3)">
+                                                       <string>
+                                                               <xsl:analyze-string select="regex-group(4)" regex="\\([\\&quot;'/btnvfr])" flags="s">
+                                                                       <xsl:matching-substring>
+                                                                               <xsl:variable name="s" select="regex-group(1)"/>
+                                                                               <xsl:choose>
+                                                                                       <xsl:when test="$s=('\', '&quot;', '''', '/')">
+                                                                                               <xsl:value-of select="regex-group(1)"/>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='b'">
+                                                                                               <!--xsl:text>&#8;</xsl:text-->
+                                                                                               <xsl:message select="'escape sequense \b is not supported by XML'"/>
+                                                                                               <xsl:text>\b</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='t'">
+                                                                                               <xsl:text>&#9;</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='n'">
+                                                                                               <xsl:text>&#10;</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='v'">
+                                                                                               <!--xsl:text>&#11;</xsl:text-->
+                                                                                               <xsl:message select="'escape sequence \v is not supported by XML'"/>
+                                                                                               <xsl:text>\v</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='f'">
+                                                                                               <!--xsl:text>&#12;</xsl:text-->
+                                                                                               <xsl:message select="'escape sequence \f is not supported by XML'"/>
+                                                                                               <xsl:text>\f</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:when test="$s='r'">
+                                                                                               <xsl:text>&#13;</xsl:text>
+                                                                                       </xsl:when>
+                                                                                       <xsl:otherwise>
+                                                                                               <xsl:message terminate="yes" select="'internal error'"/>
+                                                                                       </xsl:otherwise>
+                                                                               </xsl:choose>
+                                                                       </xsl:matching-substring>
+                                                                       <xsl:non-matching-substring>
+                                                                               <xsl:value-of select="."/>
+                                                                       </xsl:non-matching-substring>
+                                                               </xsl:analyze-string>
+                                                       </string>
+                                               </xsl:when>
+                                               <!-- double -->
+                                               <xsl:when test="regex-group(6)">
+                                                       <double>
+                                                               <xsl:value-of select="regex-group(6)"/>
+                                                       </double>
+                                               </xsl:when>
+                                               <!-- integer -->
+                                               <xsl:when test="regex-group(9)">
+                                                       <integer>
+                                                               <xsl:value-of select="regex-group(9)"/>
+                                                       </integer>
+                                               </xsl:when>
+                                               <!-- octal -->
+                                               <xsl:when test="regex-group(10)">
+                                                       <integer>
+                                                               <xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(regex-group(10), 8)"/>
+                                                       </integer>
+                                               </xsl:when>
+                                               <!-- hex -->
+                                               <xsl:when test="regex-group(11)">
+                                                       <integer>
+                                                               <xsl:value-of xmlns:Integer="java:java.lang.Integer" select="Integer:parseInt(replace(regex-group(11), '0x', ''), 16)"/>
+                                                       </integer>
+                                               </xsl:when>
+                                               <!-- symbol -->
+                                               <xsl:when test="regex-group(12)">
+                                                       <symbol>
+                                                               <xsl:value-of select="regex-group(12)"/>
+                                                       </symbol>
+                                               </xsl:when>
+                                               <!-- boolean -->
+                                               <xsl:when test="regex-group(13)">
+                                                       <boolean>
+                                                               <xsl:value-of select="regex-group(13)"/>
+                                                       </boolean>
+                                               </xsl:when>
+                                               <!-- null -->
+                                               <xsl:when test="regex-group(14)">
+                                                       <null />
+                                               </xsl:when>
+                                               <xsl:otherwise>
+                                                       <xsl:message terminate="yes" select="'internal error'"/>
+                                               </xsl:otherwise>
+                                       </xsl:choose>
+                               </xsl:matching-substring>
+                               <xsl:non-matching-substring>
+                                       <xsl:if test="normalize-space()!=''">
+                                               <xsl:message select="concat('unknown token: ', .)"/>
+                                               <xsl:value-of select="."/>
+                                       </xsl:if>
+                               </xsl:non-matching-substring>
+                       </xsl:analyze-string>
+               </xsl:variable>
+               <xsl:variable name="mode1">
+                       <xsl:apply-templates mode="json2xml1" select="$mode0/node()[1]"/>
+               </xsl:variable>
+               <xsl:variable name="mode2">
+                       <xsl:apply-templates mode="json2xml2" select="$mode1"/>
+               </xsl:variable>
+               <xsl:variable name="mode3">
+                       <xsl:apply-templates mode="json2xml3" select="$mode2"/>
+               </xsl:variable>
+               <xsl:copy-of select="$mode3"/> <!-- change $mode3 to $mode[0-2] for easy debug -->
+       </xsl:template>
+
+       <!-- json2xml1 mode: group content between {} and [] into object and array elements -->
+
+       <xsl:template mode="json2xml1" match="node()" priority="-9">
+               <xsl:copy-of select="."/>
+               <xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/>
+       </xsl:template>
+
+       <xsl:template mode="json2xml1" match="symbol[.=('}',']')]"/>
+
+       <xsl:template mode="json2xml1" match="symbol[.=('{','[')]">
+               <xsl:element name="{if (.='{') then 'object' else 'array'}">
+                       <xsl:apply-templates mode="json2xml1" select="following-sibling::node()[1]"/>
+               </xsl:element>
+               <xsl:variable name="level" select="count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])+1"/>
+               <xsl:variable name="ender"
+                       select="following-sibling::symbol[.=('}',']') and count(preceding-sibling::symbol[.=('{','[')])-count(preceding-sibling::symbol[.=('}',']')])=$level][1]"/>
+               <xsl:apply-templates mode="json2xml1" select="$ender/following-sibling::node()[1]"/>
+       </xsl:template>
+
+       <!-- json2xml2 mode: group <string>:<string|integer|double|object|array> into field element -->
+
+       <xsl:template priority="-9" mode="json2xml2" match="@*|node()">
+               <xsl:copy>
+                       <xsl:apply-templates mode="json2xml2" select="@*|node()"/>
+               </xsl:copy>
+       </xsl:template>
+
+       <xsl:template mode="json2xml2"
+               match="string[following-sibling::*[1]/self::symbol[.=':'] and following-sibling::*[2]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/>
+
+       <xsl:template mode="json2xml2"
+               match="symbol[.=':'][preceding-sibling::*[1]/self::string and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]">
+               <field name="{preceding-sibling::*[1]}">
+                       <xsl:for-each select="following-sibling::*[1]">
+                               <xsl:copy>
+                                       <xsl:apply-templates mode="json2xml2" select="@*|node()"/>
+                               </xsl:copy>
+                       </xsl:for-each>
+               </field>
+       </xsl:template>
+
+       <xsl:template mode="json2xml2"
+               match="*[self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null][preceding-sibling::*[2]/self::string and preceding-sibling::*[1]/self::symbol[.=':']]"/>
+
+       <!-- json2xml3 mode: drop comma between consecutive field and object elements -->
+
+       <xsl:template priority="-9" mode="json2xml3" match="@*|node()">
+               <xsl:copy>
+                       <xsl:apply-templates mode="json2xml3" select="@*|node()"/>
+               </xsl:copy>
+       </xsl:template>
+
+       <xsl:template mode="json2xml3" match="object/symbol[.=','][preceding-sibling::*[1]/self::field and following-sibling::*[1]/self::field]"/>
+
+       <xsl:template mode="json2xml3" match="array/symbol[.=','][preceding-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null) and following-sibling::*[1]/(self::string|self::integer|self::double|self::boolean|self::object|self::array|self::null)]"/>
+
+</xsl:stylesheet>
\ No newline at end of file
index aa41464..dca9c9e 100644 (file)
@@ -2,17 +2,21 @@
     "Failure Tests":{
         "level":4,
         "variables":{
-            "id"          : "thing",
-            "var"         : "value",
-            "hello"       : "Hello World!",
-            "empty"       : "",
-            "path"        : "/foo/bar",
-            "x"           : "1024",
-            "y"           : "768",
-            "list"        : ["red", "green", "blue"],
-            "keys"        : { "semi" : ";", "dot" : ".", "comma" : ","},
-            "example"     : "red",
-            "searchTerms" : "uri templates"
+            "id"                : "thing",
+            "var"               : "value",
+            "hello"             : "Hello World!",
+            "empty"             : "",
+            "path"              : "/foo/bar",
+            "x"                 : "1024",
+            "y"                 : "768",
+            "list"              : ["red", "green", "blue"],
+            "keys"              : { "semi" : ";", "dot" : ".", "comma" : ","},
+            "example"           : "red",
+            "searchTerms"       : "uri templates",
+            "~thing"            : "some-user",
+            "default-graph-uri" : ["http://www.example/book/","http://www.example/papers/"],
+            "query"             : "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }"
+
         },
         "testcases":[
             [ "{/id*",  false  ],
             [ "x{?empty|foo=none}" , false ],
             [ "/h{#hello+}" , false ],
             [ "/h#{hello+}" , false ],
-            [ "/vars/:var" , false ],
             [ "{keys:1}",  false  ],
             [ "{+keys:1}",  false  ],
             [ "{;keys:1*}",  false  ],
-            [ "?{-join|&|var,list}" , false ]
+            [ "?{-join|&|var,list}" , false ],
+            [ "/people/{~thing}", false],
+            [ "/sparql{?query){&default-graph-uri*}", false ],
+            [ "/resolution{?x, y}" , false ]
+
         ]
     }
 }
\ No newline at end of file
diff --git a/t/cases/transform-json-tests.xslt b/t/cases/transform-json-tests.xslt
new file mode 100644 (file)
index 0000000..d956b6b
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+       <xsl:include href="json2xml.xslt"/>
+
+       <!-- the input test files need to be supplied as a sequence of file names only (no extension) -->
+       <xsl:param name="tests" select="('extended-tests', 'negative-tests', 'spec-examples-by-section', 'spec-examples')"/>
+       <xsl:param name="json-ext" select="'json'"/>
+       <xsl:param name="xml-ext" select="'xml'"/>
+       
+       <!-- run this stylesheet with any input to generate the XML test files at output. -->
+       <!-- (a popular way of doing this is to supply the XSLT to itself as the input file.) -->
+       
+       <xsl:template match="/">
+               <xsl:for-each select="$tests">
+                       <xsl:variable name="file" select="current()"/>
+                       <xsl:variable name="json">
+                               <json>
+                                       <xsl:value-of select="unparsed-text(concat($file, '.', $json-ext))"/>
+                               </json>
+                       </xsl:variable>
+                       <xsl:variable name="xml">
+                               <xsl:apply-templates select="$json/json"/>
+                       </xsl:variable>
+                       <xsl:result-document href="{$file}.{$xml-ext}" method="xml" indent="yes">
+                               <tests>
+                                       <xsl:for-each select="$xml/json/object/field">
+                                               <test name="{@name}">
+                                                       <xsl:if test="exists(object/field[1][@name eq 'level'])">
+                                                               <xsl:attribute name="level" select="object/field[1][@name eq 'level']/integer/text()"/>
+                                                       </xsl:if>
+                                                       <variables>
+                                                               <xsl:for-each select="object/field[@name eq 'variables']/object/field">
+                                                                       <variable name="{@name}">
+                                                                               <xsl:copy-of select="*"/>
+                                                                       </variable>
+                                                               </xsl:for-each>
+                                                       </variables>
+                                                       <testcases>
+                                                               <xsl:for-each select="object/field[@name eq 'testcases']/array/array">
+                                                                       <testcase template="{*[1]}" result="{*[2]}"/>
+                                                               </xsl:for-each>                                                                 </testcases>
+                                               </test>
+                                       </xsl:for-each>
+                               </tests>
+                       </xsl:result-document>
+               </xsl:for-each>
+       </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file