Skip to content

Commit

Permalink
XML escaped characters:
Browse files Browse the repository at this point in the history
Now converts other problem characters " ' < > as well as &.
One test modified to only include &.
  • Loading branch information
SomeoneElseOSM committed Nov 30, 2014
1 parent 4d4b09b commit a97d5ae
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 11 deletions.
56 changes: 47 additions & 9 deletions src/Notes01.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,10 @@ private static void process_notes_xml( Node root_node, String passed_display_nam
{
/* ------------------------------------------------------------------------------------------------------------
* The note ID, which becomes the waypoint name on the device, is hardcoded here as "S N" + the OSM note
* number. The OSM note number is padded out to something like "<name>S N0084131</name>"
* number. The OSM note number is padded out to something like "<name>S N0278181</name>"
*
* This will become an issue when OSM note numbers go over 9,999,999. Currently OSM is on target to have a
* million notes in 6 years, so that's still some way off.
* ------------------------------------------------------------------------------------------------------------ */
note_id = "S N" + String.format( "%07d", Integer.parseInt( myGetNodeValue( this_l2_item )));

Expand Down Expand Up @@ -297,7 +300,7 @@ private static void process_notes_xml( Node root_node, String passed_display_nam
* Escape any & from in string. This must be done because MapSource doesn't like raw "&" in comment text. We
* change to "&amp;" as that's what an ampersand entered on the Garmin keyboard would come through as.
* ------------------------------------------------------------------------------------------------------------ */
comment_open_text = resolve_ampersands( comment_open_text );
comment_open_text = replace_all_escape_characters( comment_open_text );

/* ------------------------------------------------------------------------------------------------------------
* The actual "note" on the Garmin device itself will be truncated after 30 characters.
Expand Down Expand Up @@ -467,30 +470,65 @@ private static void process_notes_xml( Node root_node, String passed_display_nam
*
* A future option may be to use e.g.
* http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html
* but I'm not aware yet of anything other than ampersand that causes problems, so haven't done that yet.
*
* Issue 1 (https://github.com/SomeoneElseOSM/Notes01/issues/1) has spotted that other characters cause problems
* too. I therefore need to follow:
* http://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents
* and generalise the replacement of problem characters.
*
* Confusingly Mapsource (at least, not sure about GPS Babel et al) doesn't honour XML escaping:
* qqqdo
* ------------------------------------------------------------------------------------------------------------ */
static String resolve_ampersands( String comment_open_text )
static String replace_all_escape_characters( String comment_open_text )
{
/* ------------------------------------------------------------------------------------------------------------
* Escape & first so that we don't replace any of the & that we introduce in out replacements.
* ------------------------------------------------------------------------------------------------------------ */
char problem_char = '&';
String problem_replacement = "&amp;";
String result_text = replace_one_escape_character( comment_open_text, problem_char, problem_replacement );

problem_char = '"';
problem_replacement = "&quot;";
result_text = replace_one_escape_character( result_text, problem_char, problem_replacement );

problem_char = '<';
problem_replacement = "&lt;";
result_text = replace_one_escape_character( result_text, problem_char, problem_replacement );

problem_char = '\'';
problem_replacement = "&apos;";
result_text = replace_one_escape_character( result_text, problem_char, problem_replacement );

problem_char = '>';
problem_replacement = "&gt;";
result_text = replace_one_escape_character( result_text, problem_char, problem_replacement );

return result_text;
}


static String replace_one_escape_character( String comment_open_text, char problem_char, String problem_replacement )
{
String ampersand_replacement = "&amp;";
String result_text = comment_open_text;

int i = result_text.indexOf( '&' );
int i = result_text.indexOf( problem_char );

while ( i != -1 )
{
if ( i == 0 )
{
result_text = ampersand_replacement + result_text.substring( i+1 );
result_text = problem_replacement + result_text.substring( i+1 );
}
else
{
result_text = result_text.substring( 0, i ) + ampersand_replacement + result_text.substring( i+1 );
result_text = result_text.substring( 0, i ) + problem_replacement + result_text.substring( i+1 );
}

/* ------------------------------------------------------------------------------------------------------------
* Start searching for any text after the "&amp;" that we have just added.
* ------------------------------------------------------------------------------------------------------------ */
i = result_text.indexOf( '&', i + ampersand_replacement.length() );
i = result_text.indexOf( problem_char, i + problem_replacement.length() );
}

return result_text;
Expand Down
15 changes: 13 additions & 2 deletions test/Notes01Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,27 @@ public class Notes01Test
* that the result strings have "&amp;" where the original strings had just "&".
*
* The test strings chosen are ones "likely to cause a problem".
*
* NOTE: This test needs reworking to (a) check for replacement of the other
* characters that "replace_all_escape_characters" replaces and (b) not just
* check ampersand offset (which will be different if there's other replaced
* characters before it).
* ------------------------------------------------------------------------------ */
public void testResolve_ampersands()
{
testResolve_ampersands_string( "wibble" );
testResolve_ampersands_string( "foo & bar" );
testResolve_ampersands_string( "foo & bar & bat" );
testResolve_ampersands_string( "foo && bar" );
testResolve_ampersands_string( "<cmt>Three bus stops here - one too many. This one was originally across the road at http://www.openstreetmap.org/?mlat=53.16487 and mlon=-1.23164&zoom=18#map=18/53.16487/-1.23164 - need to check that there is a bus stop here outside the garage not the other side of Radmanthwaite Road.</cmt>" );
testResolve_ampersands_string( "Three bus stops here - one too many. This one was originally across the road at http://www.openstreetmap.org/?mlat=53.16487 and mlon=-1.23164&zoom=18#map=18/53.16487/-1.23164 - need to check that there is a bus stop here outside the garage not the other side of Radmanthwaite Road." );
testResolve_ampersands_string( "" );
testResolve_ampersands_string( "&" );
testResolve_ampersands_string( "&&" );
}

private void testResolve_ampersands_string( String test1 )
{
String test2 = Notes01.resolve_ampersands( test1 );
String test2 = Notes01.replace_all_escape_characters( test1 );
testResolve_ampersands_string_test( test1, test2 );
}

Expand All @@ -45,6 +50,12 @@ private void testResolve_ampersands_string_test( String test1, String test2 )
* ------------------------------------------------------------------------------ */
int i1 = test1.indexOf( "&" );
int i2 = test2.indexOf( "&amp;" );
System.out.println();
System.out.println( test1 );
System.out.println( i1 );
System.out.println( test2 );
System.out.println( i2 );

assertEquals( i1, i2 );

/* ------------------------------------------------------------------------------
Expand Down

0 comments on commit a97d5ae

Please sign in to comment.