I'm trying to add/update a property in a .plist
file using an XPath key specification. I've tested with a file that looks like this:
<?xml version="1.0"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="1.0">
<dict>
<key>testProp</key>
<array>
<string>text</string>
<string>54</string>
<string>2023-11-09T16:29:34Z</string>
</array>
<key>objectProp</key>
<array>
<string>text</string>
<integer>54</integer>
<date>2023-11-09T16:29:34Z</date>
</array>
</dict>
</plist>
and an XMLPropertyListConfiguration
object built like this:
File file = new File("path/to/config.plist");
XMLPropertyListConfiguration configuration =
new FileBasedConfigurationBuilder<>(XMLPropertyListConfiguration.class)
.configure(new Parameters().xml()
.setFile(file)
.setExpressionEngine(new XPathExpressionEngine()))
.getConfiguration();
// do any changes, then save the file using:
FileHandler handler = new FileHandler(configuration);
handler.save(file);
My goal: edit a value in one of the array properties, or insert a new value into the array. I had thought that configuration.setProperty("/testProp[2]", "a different string")
would result in the following (some parts cut for brevity):
<key>testProp</key>
<array>
<string>text</string>
<string>a different string</string>
<string>2023-11-09T16:29:34Z</string>
</array>
but instead it added testProp[2]
as its own property:
<?xml version="1.0"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="1.0">
<dict>
<key>testProp</key>
<array>
<string>text</string>
<string>54</string>
<string>2023-11-09T16:29:34Z</string>
</array>
<key>objectProp</key>
<array>
<string>text</string>
<integer>54</integer>
<date>2023-11-09T16:29:34Z</date>
</array>
<key>testProp[2]</key>
<string>a different string</string>
</dict>
</plist>
It's my understanding that you use the testProp[n]
predicate to specify the nth property/value of testProp
, but clearly that's not the case here. Is there something I'm missing about arrays specifically? Or would I have to read testProp
as a List
, modify the list, and then save the whole list back as testProp
? The best solution I'm looking for is something that can include all relevant information in the XPath string, but if I need to handle the index in the array separately that can be handled too.
As far as I can tell, you cannot use standard XPath expressions to access plist properties items. configuration.getProperty("/testProp");
returns an ArrayList<String>
with the value [text, 54, 2023-11-09T16:29:34Z]
. I tried various XPath expressions to access list indices(e.g./testProp[1][1]
, /testProp[1]/child:1
), but none of them worked. Therefore, you might need to modify the ArrayList
directly and set testProp
as a whole.
File file = new File("path/to/config.plist");
XMLPropertyListConfiguration configuration =
new FileBasedConfigurationBuilder<>(XMLPropertyListConfiguration.class)
.configure(new Parameters().xml()
.setFile(file)
.setExpressionEngine(new XPathExpressionEngine()))
.getConfiguration();
// Java 17 grammar
var testProp = configuration.getProperty("/testProp");
if (testProp instance of ArrayList testPropList) {
testPropList.set(1, "a different string"); // change the 2nd string to 'a different string'
}
configuration.setProperty("testProp", testProp); // set the whole 'testProp'
FileHandler handler = new FileHandler(configuration);
handler.save(file);