28

In <string-array name="versions"> I have this beast of an entry (boiled down to a reasonable minimum to reproduce the effect):

<item>100% foo 40%bar</item>

which produces these errors:

Multiple annotations found at this line:
- error: Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?
- error: Found tag </item> where </string-array> is expected

Adding formatted="false" doesn't change a thing.

<item>100&#37; foo 40&#37;bar</item>

results in the same error messages. WTH?

<item>100% foo 40bar</item>
<item>100 foo 40%bar</item>
<item>100% foo 40%</item>

would all work fine. Escaping it with \% is just ignored resulting in the same error. %% doesn't result in an error but I get %%.

Giszmo
  • 1,944
  • 2
  • 20
  • 47
  • http://stackoverflow.com/questions/4414389/android-xml-percent-symbol/4417333#4417333 , most of that you say won't work, but see the last option. – Julian Fondren Feb 22 '12 at 00:23
  • Thanx for the answer. Unfortunately I am not dealing with a string that might allow substitution at all unless there is a way to do substitutions in arrays. In my arrays.xml there is a string-array with items. These I load via getResources().getStringArray(R.array.versions); – Giszmo Feb 22 '12 at 08:07
  • ouch, getStringArray uses the formatter and yet doesn't allow you to pass format arguments. I'm afraid that you'll have to recreate the array after you load it, substiting in the %, or else correct the strings as you use them. – Julian Fondren Feb 22 '12 at 08:22
  • Java strings are immutable. The methods return copies. – Julian Fondren Feb 22 '12 at 11:05
  • :/ urgs. Me stupid. Sorry. Much stress right now. – Giszmo Feb 22 '12 at 11:46
  • Yes, this last question about replaceAll was not necessary but I don't like the solution for the first one. I would say that's a bug. Thanx Julian. – Giszmo Feb 22 '12 at 11:53
  • can you resort to some variation of the percent sign in the first place ? e.g. try \u066a ([arabic percent sign](http://www.fileformat.info/info/unicode/char/66A/index.htm)). – collapsar Mar 01 '12 at 18:48
  • 1
    haha collapsar :) I like your idea but I settled with %% and subsequent string replacement. So I can't pick your solution for others that run into the same issue? – Giszmo Mar 02 '12 at 00:58

3 Answers3

46

The % is a reserved character in XML like <, >, etc. Use %% for each % you are using in the string resource.

Binoy Babu
  • 16,699
  • 17
  • 91
  • 134
Ali Azhar
  • 1,703
  • 19
  • 14
  • 3
    You are slightly late with your reply but thanks anyway :D I might test your solution if I come accross Android development soon but given I had tried `%` I though I had done enough of escaping back then. `\%%` is definitely nicer than `\u0025` … well … maybe not "definitely". :) – Giszmo Jun 04 '15 at 00:17
  • 4
    `%%` was the only one that work for me. This is my final string `(%1$s%% commission)` that translates, for example, in `(2.56% commission)` – Laranjeiro Jul 28 '15 at 09:23
  • 8
    % most certainly is not a reserved character in XML; this content restriction is specific to Android resource files. – Cumbayah Mar 06 '16 at 21:04
  • Thanks, save my hours – Ho Luong Aug 02 '20 at 16:09
25

Encoding each as a unicode character in the xml works for me:

<string name="test">100\u0025 foo 40\u0025bar</string>
Mark D
  • 3,317
  • 1
  • 26
  • 27
  • 1
    Ok, I guess this should be the way to go. Still I would like to understand why both % and \u0025 are % but version 1 makes me run into the error?? – Giszmo Mar 22 '12 at 16:12
  • 3
    I lost one good 20 minutes on this, so I hope can save time for someone else. Having String to format, I had to use e.g., Score: %.2f%%. Two % character, attached to the format. None of the above worked in this case. – donnadulcinea Mar 11 '14 at 11:41
  • 5
    I would not recommand replacing % with unicode character. They are encoded but not escaped. If you have parameter within your sentence like Value in percent : %1$d \u0025 and call " int testValue = 29; String text = getResources().getString(R.string.test, testValue);" your application will only crash... Instead use %% (or eventually Value %1$d \u0025\u0025 would work but really dirty) – ClemM Sep 05 '16 at 17:32
1

Using CDATA may work..

<item><![CDATA[100% foo 40%]]></item>
C.d.
  • 9,932
  • 6
  • 41
  • 51