You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2020/04/22 22:06:16 UTC

[jena] branch master updated: JENA-1887: SplitIRI fix

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/master by this push:
     new 360b4d7  JENA-1887: SplitIRI fix
     new 93cc41c  Merge pull request #732 from afs/split-iri
360b4d7 is described below

commit 360b4d7912c8370f5e74ac4a38b82c05ab203334
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Apr 21 20:50:48 2020 +0100

    JENA-1887: SplitIRI fix
---
 .../main/java/org/apache/jena/util/SplitIRI.java   | 131 ++++++++++++---------
 .../org/apache/jena/util/TestSplitIRI_TTL.java     |  49 ++++----
 .../org/apache/jena/util/TestSplitIRI_XML.java     |  70 +++++------
 3 files changed, 141 insertions(+), 109 deletions(-)

diff --git a/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java b/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java
index 0b0d65b..1190647 100644
--- a/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java
+++ b/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java
@@ -29,22 +29,22 @@ import org.apache.jena.rdf.model.impl.Util ;
  * <p>
  * For display, use {@link #localname} and {@link #namespace}.
  * This follows Turtle, adds some pragmatic rulesm but does not escape
- * any characters. A URI is split never split before the last {@code /} 
+ * any characters. A URI is split never split before the last {@code /}
  * or last {@code #}, if present.
  * See {@link #splitpoint} for more details.
  * <p>
  * This code form the machinary behind {@link Node#getLocalName}
- * {@link Node#getNameSpace} for URI Nodes.   
+ * {@link Node#getNameSpace} for URI Nodes.
  * <p>
  * {@link #localnameTTL} is strict Turtle; it is the same local name as
  * before, but escaped if necessary.
  * <p>
  * The functions {@link #namespaceXML} and {@link #localnameXML}
- * apply the rules for XML qnames. 
+ * apply the rules for XML qnames.
  */
 public class SplitIRI
 {
-    /** Return the 'namespace' (prefix) for a URI string. 
+    /** Return the 'namespace' (prefix) for a URI string.
      * Use with {@link #localname}
      */
     public static String namespace(String string) {
@@ -53,7 +53,7 @@ public class SplitIRI
             return string ;
         return string.substring(0, i) ;
     }
-    
+
     /** Calculate a localname - do not escape PN_LOCAL_ESC.
      * This is not guaranteed to be legal Turtle.
      * Use with {@link #namespace}
@@ -64,8 +64,8 @@ public class SplitIRI
             return "" ;
         return string.substring(i) ;
     }
-    
-    /** Return the 'namespace' (prefix) for a URI string, 
+
+    /** Return the 'namespace' (prefix) for a URI string,
      * legal for Turtle and goes with {@link #localnameTTL}
      */
     public static String namespaceTTL(String string) {
@@ -82,12 +82,12 @@ public class SplitIRI
             return x ;
         return escape_PN_LOCAL_ESC(x) ;
     }
-    
+
     private static String escape_PN_LOCAL_ESC(String x) {
         // Assume that escapes are rare so scan once to make sure there
         // is work to do then scan again doing the work.
         //'\' ('_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%')
-        
+
         int N = x.length() ;
         boolean escchar = false ;
         for ( int i = 0 ; i < N ; i++ ) {
@@ -107,26 +107,25 @@ public class SplitIRI
                 sb.append('\\') ;
             sb.append(ch) ;
         }
-        return sb.toString() ; 
+        return sb.toString() ;
     }
 
     private static boolean needsEscape(char ch, boolean finalChar) {
         if ( ch == '.' )
             return finalChar ;
-        return isPN_LOCAL_ESC(ch) ; 
+        return isPN_LOCAL_ESC(ch) ;
     }
-    
-    
+
     // @formatter:off
     /* From the RDF 1.1 Turtle specification:
         [136s]  PrefixedName    ::=     PNAME_LN | PNAME_NS
         Productions for terminals
-        
+
         [163s]  PN_CHARS_BASE   ::=     [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
         [164s]  PN_CHARS_U  ::=     PN_CHARS_BASE | '_'
         [166s]  PN_CHARS    ::=     PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
         [167s]  PN_PREFIX   ::=     PN_CHARS_BASE ((PN_CHARS | '.')* PN_CHARS)?
-        
+
         [168s]  PN_LOCAL    ::=     (PN_CHARS_U | ':' | [0-9] | PLX) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX))?
         [169s]  PLX     ::=     PERCENT | PN_LOCAL_ESC
         [170s]  PERCENT     ::=     '%' HEX HEX
@@ -136,45 +135,66 @@ public class SplitIRI
     // @formatter:on
 
     /** Find the URI split point, return the index into the string that is the
-     *  first character of a legal Turtle local name.   
+     *  first character of a legal Turtle local name.
      * <p>
      * This is a pragmatic choice, not just finding the maximal point.
-     * For example, with escaping '/' can be included but that means 
+     * For example, with escaping '/' can be included but that means
      * {@code http://example/path/abc} could split to give {@code http://example/}
      * and {@code path/abc} .
      * <p>
-     * Split URN's after ':'.  
-     *   
+     * Split URN's after ':'.
+     *
      * @param uri URI string
      * @return The split point, or -1 for "not found".
      */
-    
     public static int splitpoint(String uri) {
         boolean isURN = uri.startsWith("urn:") ;
         // Fast track.  Still need to check validity of the prefix part.
         int idx1 = uri.lastIndexOf('#') ;
-        // Not so simple - \/ in local names 
+        // Not so simple - \/ in local names
         int idx2 = isURN ? uri.lastIndexOf(':') : uri.lastIndexOf('/') ;
 
         // If absolute.
-        int idx3 = uri.indexOf(':') ; 
-    
+        int idx3 = uri.indexOf(':') ;
+
         // Note: local names can't end in "." in Turtle.
         // This is handled by escape_PN_LOCAL_ESC which will escape it as "\."
-        
-        // Test the discovered local part.
-        // Limit is exclusive.
-        int limit = Math.max(idx1, idx2) ;
-        limit = Math.max(limit, idx3) ;
-        limit = Math.max(-1, limit) ;
-        
+
+        // Cases
+        //   "abc#def"
+        //   "/abc"
+        //   "/"
+        //   "/path/path#frag
+        //   "/path/path#abc/def" :: / in fragment, split is at the "#".
+
+        int limit;
+        if ( idx1 >= 0 && idx2 < 0 ) {
+            // No path "/" (or ":" if a URN)
+            limit = idx1;
+        } else if ( idx1 < 0 && idx2 >= 0 ) {
+            // No fragment
+            limit = idx2;
+        } else if ( idx1 >= 0 && idx2 >= 0 ) {
+            // Fragment and path. Use fragment.
+            // If "/" is in the fragment, it is not the split point.
+            limit = idx1 ;
+        } else {
+            limit = -1;
+        }
+
+        // At least idx3, the case of no "/" and no "#" in an absolute IRI
+        if ( idx3 >= 0 )
+            limit = Math.max(limit, idx3) ;
+
+        // Limit is our guess.
+        // Now search end of URI to this guess checking the characters found.
+
         int splitPoint = -1 ;
-        // Work backwards, checking for 
+        // Work backwards, checking for
         // ((PN_CHARS | '.' | ':' | PLX)*
         for ( int i = uri.length()-1 ; i > limit ; i-- ) {
             char ch = uri.charAt(i) ;
-            
-            if ( /*RiotChars.*/isPNChars_U_N(ch) || /*RiotChars.*/isPN_LOCAL_ESC(ch) || ch == ':' || ch == '-' || ch == '.' ) 
+            if ( /*RiotChars.*/isPNChars_U_N(ch) || /*RiotChars.*/isPN_LOCAL_ESC(ch) || ch == ':' || ch == '-' || ch == '.' )
                 continue ;
             splitPoint = i+1 ;
             break ;
@@ -185,10 +205,10 @@ public class SplitIRI
         // No split point.
         if ( splitPoint >= uri.length() )
             return -1 ;
-        
+
         // Check the first character of the local name.
-        // All character are legal localname name characters but may not satisfy the additional
-        // first character rule.  Move forward to first legal first character.    
+        // All characters are legal localname name characters but may not satisfy the additional
+        // first character rule.  Move forward to first legal first character.
         int ch = uri.charAt(splitPoint) ;
         while ( ch == '.' || ch == '-' ) {
             splitPoint++ ;
@@ -200,7 +220,7 @@ public class SplitIRI
         // Checking the final '.' is done when checking for escapes.
         return splitPoint ;
     }
-    
+
     private static boolean checkhex(String uri, int i) {
         return /*RiotChars.*/isHexChar(uri.charAt(i)) ;
     }
@@ -209,7 +229,7 @@ public class SplitIRI
     // for %XX.  If illegal (e.g. %X), the best we can do
     // is not mess them up.
     /*
-        // %  - just need to check that it is followed by two hex. 
+        // %  - just need to check that it is followed by two hex.
         if ( ch == '%' ) {
             if ( i+2 >= uri.length() ) {
                 // Too short
@@ -218,7 +238,7 @@ public class SplitIRI
             if ( ! checkhex(uri, i+1) || ! checkhex(uri, i+2) )
                 return -1 ;
         }
-     
+
      */
     /** Split point, according to XML qname rules.
      * This is the longest NCName at the end of the uri.
@@ -229,20 +249,20 @@ public class SplitIRI
     /** Namespace, according to XML qname rules.
      * Use with {@link #localnameXML}.
      */
-    public static String namespaceXML(String string) { 
+    public static String namespaceXML(String string) {
         int i = splitXML(string) ;
         return string.substring(0, i) ;
     }
 
     /** Localname, according to XML qname rules. */
-    public static String localnameXML(String string) { 
+    public static String localnameXML(String string) {
         int i = splitXML(string) ;
         return string.substring(i) ;
     }
 
     // Extracted from RiotChars
-    // When/if RIOT becomes accessible to this code, then refactor 
-    
+    // When/if RIOT becomes accessible to this code, then refactor
+
     private static boolean /*RiotChars.*/isPN_LOCAL_ESC(char ch) {
         switch (ch) {
             case '\\': case '_':  case '~': case '.': case '-': case '!': case '$':
@@ -258,42 +278,42 @@ public class SplitIRI
     private static boolean isDigit(int ch) {
         return range(ch, '0', '9') ;
     }
-    
+
     private static boolean isPNCharsBase(int ch) {
-        // PN_CHARS_BASE ::= [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | 
+        // PN_CHARS_BASE ::= [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] |
         //                   [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] |
-        //                   [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | 
+        //                   [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
         //                   [#x10000-#xEFFFF]
-        return 
+        return
             r(ch, 'a', 'z') || r(ch, 'A', 'Z') || r(ch, 0x00C0, 0x00D6) || r(ch, 0x00D8, 0x00F6) || r(ch, 0x00F8, 0x02FF) ||
             r(ch, 0x0370, 0x037D) || r(ch, 0x037F, 0x1FFF) || r(ch, 0x200C, 0x200D) || r(ch, 0x2070, 0x218F) ||
             r(ch, 0x2C00, 0x2FEF) || r(ch, 0x3001, 0xD7FF) ||
             // Surrogate pairs
             r(ch, 0xD800, 0xDFFF) ||
-            r(ch, 0xF900, 0xFDCF) || r(ch, 0xFDF0, 0xFFFD) || 
-            r(ch, 0x10000, 0xEFFFF) ; // Outside the basic plain. 
+            r(ch, 0xF900, 0xFDCF) || r(ch, 0xFDF0, 0xFFFD) ||
+            r(ch, 0x10000, 0xEFFFF) ; // Outside the basic plane.
     }
-    
+
     private static boolean isPNChars_U(int ch) {
         //PN_CHARS_BASE | '_'
         return isPNCharsBase(ch) || ( ch == '_' ) ;
     }
-    
+
     private static boolean isPNChars_U_N(int ch) {
-        // PN_CHARS_U | [0-9] 
+        // PN_CHARS_U | [0-9]
         return isPNCharsBase(ch) || ( ch == '_' ) || isDigit(ch) ;
     }
-    
+
     private static boolean isPNChars(int ch) {
         // PN_CHARS ::=  PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
         return isPNChars_U(ch) || isDigit(ch) || ( ch == '-' ) || ch == 0x00B7 || r(ch, 0x300, 0x036F) || r(ch, 0x203F, 0x2040) ;
     }
-    
+
     /** Hexadecimal character */
     private static boolean isHexChar(int ch) {
         return range(ch, '0', '9') || range(ch, 'a', 'f') || range(ch, 'A', 'F') ;
     }
-    
+
     private static int valHexChar(int ch) {
         if ( range(ch, '0', '9') )
             return ch - '0' ;
@@ -309,6 +329,5 @@ public class SplitIRI
     private static boolean range(int ch, char a, char b) {
         return (ch >= a && ch <= b) ;
     }
-    
 }
 
diff --git a/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_TTL.java b/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_TTL.java
index d3d5a7e..0d302ec 100644
--- a/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_TTL.java
+++ b/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_TTL.java
@@ -26,13 +26,16 @@ import junit.framework.JUnit4TestAdapter ;
 import org.junit.Assert ;
 import org.junit.Test ;
 
-/** Test splitting IRI strings using Turtle rules.
+/**
+ * Test splitting IRI strings using Turtle rules.
+ * Includes the generally splitting for display - the
+ * difference is that for Turtle, some characters need escaping.
  */
 public class TestSplitIRI_TTL {
     public static junit.framework.Test suite() {
         return new JUnit4TestAdapter(TestSplitIRI_TTL.class) ;
     }
-    
+
     // Basics
     @Test public void split_basic_00() { testSplit("http://example/foo", "http://example/".length()) ; }
     @Test public void split_basic_01() { testPrefixLocalname("http://example/foo",            "http://example/",      "foo"       ) ; }
@@ -44,12 +47,12 @@ public class TestSplitIRI_TTL {
     @Test public void split_basic_07() { testPrefixLocalname("http://example/xyz#1.2.3.4",    "http://example/xyz#",  "1.2.3.4"   ) ; }
     @Test public void split_basic_08() { testPrefixLocalname("http://example/xyz#_abc",       "http://example/xyz#",  "_abc"      ) ; }
     @Test public void split_basic_09() { testPrefixLocalname("http://example/xyz/_1.2.3.4",   "http://example/xyz/", "_1.2.3.4"   ) ; }
-    
-    // Relative URIs 
+
+    // Relative URIs
     @Test public void split_rel_1() { testPrefixLocalname("xyz/_1.2.3.4",  "xyz/", "_1.2.3.4" ) ; }
     @Test public void split_rel_2() { testPrefixLocalname("xyz",           "",     "xyz" ) ; }
     @Test public void split_rel_3() { testPrefixLocalname("",              "",     "" ) ; }
-    
+
     // Bizarre but legal URIs
     @Test public void split_weird_1() { testPrefixLocalname("abc:def",       "abc:", "def" ) ; }
 
@@ -66,21 +69,28 @@ public class TestSplitIRI_TTL {
     @Test public void split_ttl_06() { testPrefixLocalname("abc:xyz/-.-.-def",       "abc:xyz/-.-.-", "def" ) ; }
     @Test public void split_ttl_07() { testPrefixLocalname("http://example/id=89",          "http://example/",      "id=89"   ) ; }
     // Trailing '.'
-    @Test public void split_ttl_08() { testPrefixLocalname("http://example/2.3.",           "http://example/",      "2.3."     ) ; }
-    
+    @Test public void split_ttl_08() { testPrefixLocalname("http://example/2.3.",          "http://example/",  "2.3."    ) ; }
+
     // Turtle details, including escaping.
     // Test for PrefixLocalnameEsc
-    @Test public void split_ttl_esc_01() { testPrefixLocalnameEsc("http://example/id=89",  "http://example/", "id\\=89"   ) ; }
-    @Test public void split_ttl_esc_02() { testPrefixLocalnameEsc("http://example/a,b",  "http://example/", "a\\,b"   ) ; }
+    @Test public void split_ttl_esc_01() { testPrefixLocalnameEsc("http://example/id=89",  "http://example/",  "id\\=89"  ) ; }
+    @Test public void split_ttl_esc_02() { testPrefixLocalnameEsc("http://example/a,b",  "http://example/", "a\\,b"       ) ; }
     // Trailing '.'
-    @Test public void split_ttl_esc_03() { testPrefixLocalnameEsc("http://example/2.3.", "http://example/", "2.3\\."     ) ; }
-    
+    @Test public void split_ttl_esc_03() { testPrefixLocalnameEsc("http://example/2.3.", "http://example/", "2.3\\."      ) ; }
+
     // URNs split differently.
-    @Test public void split_urn_01() { testPrefixLocalname("urn:foo:bar",                   "urn:foo:",              "bar"       ) ; }
+    @Test public void split_urn_01() { testPrefixLocalname("urn:foo:bar",     "urn:foo:", "bar") ; }
+    @Test public void split_urn_02() { testPrefixLocalname("urn:example:bar/b",   "urn:example:", "bar/b"); }
+    @Test public void split_urn_03() { testPrefixLocalname("urn:example:bar#frag",   "urn:example:bar#", "frag"); }
+
+
+    // Fragments, including Turtle escapes.
+    @Test public void split_frag_01() { testPrefixLocalname("http://example/foo#bar:baz", "http://example/foo#", "bar:baz"     ) ; }
+    @Test public void split_frag_02() { testPrefixLocalnameEsc("http://example/abc/def#ghi/jkl", "http://example/abc/def#", "ghi\\/jkl"); }
+    @Test public void split_frag_03() { testPrefixLocalnameEsc("urn:example:abc#ghi:jkl", "urn:example:abc#", "ghi:jkl"); }
+    @Test public void split_frag_04() { testPrefixLocalnameEsc("urn:example:abc#ghi/jkl", "urn:example:abc#", "ghi\\/jkl"); }
+    @Test public void split_frag_05() { testPrefixLocalnameEsc("urn:example:abc#ghi:jkl", "urn:example:abc#", "ghi:jkl"); }
 
-    // Anti-tests
-    @Test public void split_51() { testPrefixLocalnameNot("http://example/foo#bar:baz", "http://example/foo#bar", "baz"     ) ; }
-    
     private void testSplit(String string, int expected) {
         int i = splitpoint(string) ;
         Assert.assertEquals(expected, i) ;
@@ -95,7 +105,7 @@ public class TestSplitIRI_TTL {
             ns = string.substring(0, i) ;
             ln = string.substring(i) ;
         }
-        
+
         if ( expectedPrefix != null )
             Assert.assertEquals(expectedPrefix, ns);
         if ( expectedLocalname != null )
@@ -117,7 +127,7 @@ public class TestSplitIRI_TTL {
         }
         Assert.assertEquals(msg, -1, i) ;
     }
-    
+
     // Don't worry about local name escaping.
     private void testPrefixLocalname(String string, String expectedNamespace, String expectedLocalname) {
         String actualNamespace = namespace(string) ;
@@ -137,9 +147,9 @@ public class TestSplitIRI_TTL {
                              expectedNamespace, namespaceTTL(string),
                              expectedLocalname, localnameTTL(string)) ;
     }
-    
+
     private void checkPrefixLocalname(String string,
-                                      String expectedNamespace, String actualNamespace, 
+                                      String expectedNamespace, String actualNamespace,
                                       String expectedLocalname, String actualLocalName) {
         if ( expectedNamespace != null )
             Assert.assertEquals(expectedNamespace, actualNamespace);
@@ -161,4 +171,3 @@ public class TestSplitIRI_TTL {
         Assert.assertEquals(string, x) ;
     }
 }
-
diff --git a/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_XML.java b/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_XML.java
index 5719886..a00b919 100644
--- a/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_XML.java
+++ b/jena-core/src/test/java/org/apache/jena/util/TestSplitIRI_XML.java
@@ -22,37 +22,43 @@ import junit.framework.JUnit4TestAdapter;
 import org.apache.jena.rdf.model.impl.Util ;
 import org.junit.Test;
 import static org.junit.Assert.*;
+
+/**
+ * Tests of splitting with RDF/XML rules, where the local name is more restricted
+ * (e.g. can not start with a digit because XML qnames can have a digit immediately
+ * after the ":").
+ *
+ * This in turn leads to unexpected namespace strings.
+ */
 public class TestSplitIRI_XML
 {
      public static junit.framework.Test suite() {
          return new JUnit4TestAdapter(TestSplitIRI_XML.class) ;
      }
-    
-    // Intermediate : JUnit 3 and JUnit 4.
-     
+
     @Test public void splitNS_01()
     { split("http://example/xyz", "http://example/", "xyz") ; }
-    
+
     @Test public void splitNS_02()
     { split("http://example/ns#xyz", "http://example/ns#", "xyz") ; }
-    
+
     @Test public void splitNS_03()
     { no_split("http://example/ns#") ; }
-    
+
     @Test public void splitNS_04()
     { no_split("http://example/") ; }
-    
+
     @Test public void splitNS_05()  // Illegal URI
     { split("http://example", "http://", "example") ; }
-    
+
     @Test public void splitNS_06()   // localname must be at least the NCStartChar - not empty
     { split("mailto:me", "mailto:m", "e") ; }
 
     @Test public void splitNS_07()
-    { split("urn:abc:xyz","urn:abc:", "xyz") ; } 
+    { split("urn:abc:xyz","urn:abc:", "xyz") ; }
 
     @Test public void splitNS_08()
-    { no_split("urn:abc:xyz:") ; } 
+    { no_split("urn:abc:xyz:") ; }
 
     @Test public void splitNS_09()
     { split("http://bio2rdf.org/pdb:Pentane-3%2C4-diol-5-phosphate", "http://bio2rdf.org/pdb:Pentane-3%2C4-", "diol-5-phosphate") ; }
@@ -60,54 +66,54 @@ public class TestSplitIRI_XML
     @Test public void splitNS_10()
     { split("http://bio2rdf.org/pdb:Pentane-3,4-diol-5-phosphate", "http://bio2rdf.org/pdb:Pentane-3,4-", "diol-5-phosphate") ; }
 
-    // Don't split inside a %encoding. 
+    // Don't split inside a %encoding.
     @Test public void splitNS_11()
-    { split("http://host/abc%AAdef", "http://host/abc%AA", "def") ; } 
+    { split("http://host/abc%AAdef", "http://host/abc%AA", "def") ; }
 
     @Test public void splitNS_12()
-    { split("http://host/abc%1Adef", "http://host/abc%1A", "def") ; } 
-    
+    { split("http://host/abc%1Adef", "http://host/abc%1A", "def") ; }
+
     @Test public void splitNS_13()
-    { split("http://host/abc%A1def", "http://host/abc%A1", "def") ; } 
-    
+    { split("http://host/abc%A1def", "http://host/abc%A1", "def") ; }
+
     @Test public void splitNS_14()
-    { split("http://host/abc%AA22def", "http://host/abc%AA22", "def") ; } 
+    { split("http://host/abc%AA22def", "http://host/abc%AA22", "def") ; }
 
     @Test public void splitNS_15()
-    { no_split("http://host/abc%AA22") ; } 
+    { no_split("http://host/abc%AA22") ; }
 
     // Other schemes
-    
+
     @Test public void splitNS_50()
-    { split("file:///x/y", "file:///x/", "y") ; } 
+    { split("file:///x/y", "file:///x/", "y") ; }
 
     @Test public void splitNS_51()
-    { split("file:///x", "file:///", "x") ; } 
+    { split("file:///x", "file:///", "x") ; }
 
     @Test public void splitNS_52()
-    { split("file:x", "file:", "x") ; } 
+    { split("file:x", "file:", "x") ; }
 
     @Test public void splitNS_53()
     // Not ideal but some URI schemes dislike a URI with just the scheme
-    { split("file:foo", "file:", "foo") ; } 
+    { split("file:foo", "file:", "foo") ; }
 
     @Test public void splitNS_54()
-    { split("file:c:/foo", "file:c:/", "foo") ; } 
-    
+    { split("file:c:/foo", "file:c:/", "foo") ; }
+
     // urn:uuid:d871c7f4-2926-11b2-8073-a5e169788449 - legal type 1 uuid as urn
     // uuid:3cf3e43a-3a5d-40d8-a93c-8697b162a1c0 - legal type 4 uuid as uri
-    
+
     @Test public void splitNS_55()
     { split("urn:uuid:d871c7f4-2926-11b2-8073-a5e169788449", "urn:uuid:", "d871c7f4-2926-11b2-8073-a5e169788449") ; }
 
     @Test public void splitNS_56()
     { split("uuid:3cf3e43a-3a5d-40d8-a93c-8697b162a1c0", "uuid:3", "cf3e43a-3a5d-40d8-a93c-8697b162a1c0") ; }
-    
+
     @Test public void splitNS_57()
     { split("urn:abc:def", "urn:abc:", "def") ; }
 
     // --------
-    
+
     static void  no_split(String string)
     { split(string, null, null) ; }
 
@@ -117,15 +123,15 @@ public class TestSplitIRI_XML
             fail("Bad test - namespace is null but local name is not") ;
         if ( namespace != null && localname == null )
             fail("Bad test - namespace is not null but local name is") ;
-        
+
         int idx = Util.splitNamespaceXML(uriStr) ;
-        if ( idx == uriStr.length() ) 
+        if ( idx == uriStr.length() )
         {
             // No split.
             if ( namespace != null )
                 fail("Expected a split ("+namespace+","+localname+") - but none found") ;
             return ;
-            
+
         }
         // Split
         String ns = uriStr.substring(0,idx) ;
@@ -133,6 +139,4 @@ public class TestSplitIRI_XML
         assertEquals(namespace, ns) ;
         assertEquals(localname, ln) ;
     }
-    
-    
 }