10

I would like to know whether there is a way to insert/inject a <string> element defined in an XML file into another <string> element, doing that just with XML.

For example I could have:

<string name="author">Francesco</string>`

and I am looking for something like:

<string name="about_application">Author: @string/author</string>`

so that getString(R.string.about_application) would result in "Author: Francesco".

I know that I could combine the two elements in Java code using String.format(string, formatArgs)like for example:

<string name="author">Francesco</string>
<string name="about_application">Author: %1$s</string>`

and then in code use

String.format(getString(R.string.about_application), getString(R.string.author))

but I would like to do it in XML directly.

Can anyone suggest me a way to do it?

Volo
  • 28,673
  • 12
  • 97
  • 125
Francesco Feltrinelli
  • 1,589
  • 1
  • 10
  • 14

4 Answers4

15

If I understand what you are looking to do, then internal (parsed) general entities might help you achieve what you are looking for.

An example of how you can define the value "Francesco" as an entity called "auth" and then use it in your XML:

<?xml version="1.0"?>
<!DOCTYPE doc [
  <!ENTITY auth "Francesco">
]>
<doc>
  <string name="author">&auth;</string>
  <string name="about_application">Author: &auth;</string>
</doc>

When read by an XML parser, the document will be parsed and evaluated, or "seen", as:

<?xml version="1.0"?>
<doc>
  <string name="author">Francesco</string>
  <string name="about_application">Author: Francesco</string>
</doc>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • Thank you! It works well when I reference an internal entity from an xml element in the same file, while I am having problems to reference an external entity defined in another xml file. Anyway, I am not sure whether this kind of mechanism should be used with Android /res/values/ xml files, I think it is a little far from Android "standard" way of manage them. – Francesco Feltrinelli Sep 16 '10 at 09:55
  • 2
    This is like an indirection on top of the indirection :-). The problem may be that when translating the string.xml (copies in other folders), you forget to localize &auth;. Besides, every translation still needs all the string tags containing &auth; then. But yeah, that's the best possible because it has to be static (so the xml files can be made binary). – pjv Mar 31 '12 at 17:35
1

Unfortunately I don't think that is possible. I asked a similar question a while ago, and was told it wasn't possible.

Community
  • 1
  • 1
Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82
0

Gradle plugin 0.10 brings what they call manifestPlaceholders which basically does what you need but this feature currently only work in the AndroidManifest. There is although an issue opened targeting the next Android build version 1.4 (1.3 is currently in beta4 so should be near RC1 and could see a 1.4 beta1 soon hopefully).

This issue should expand the placeholders in xml configurations files (I just pray this will include strings file and not only basic xml configuration).

From: http://tools.android.com/tech-docs/new-build-system

For custom placeholders replacements, use the following DSL to configure the placeholders values :

android {
        defaultConfig {
            manifestPlaceholders = [ activityLabel:"defaultName"]
        }
        productFlavors {
            free {
            }
            pro {
                manifestPlaceholders = [ activityLabel:"proName" ]
            }
        }

will substitute the placeholder in the following declaration :

<activity android:name=".MainActivity"> android:label="${activityLabel}" >

Can't wait to try it out. This way you could put a placeholder in multiple occurence in the strings file and define the value only in one place instead of modifying all java files to add an argument with %1$s

For now the only clean solution is although the entity trick but this will not work if you want to override the value in flavors since the entity must be defined in the same xml file.

Eric Labelle
  • 1,987
  • 2
  • 15
  • 23
0

Yes it is possible, I've created this small library that allows you to resolve these placeholders at buildtime, so you won't have to add any Java/Kotlin code to make it work.

Based on your example, you'd have to set up your string like this:

<string name="author">Francesco</string>
<string name="about_application">Author: ${author}</string>

And then the plugin will take care of creating the following:

<!-- Auto generated during compilation -->
<string name="about_application">Author: Francesco</string>

More info here: https://github.com/LikeTheSalad/android-stem

César Muñoz
  • 535
  • 1
  • 6
  • 10