Just seen this post from Amber while composing this reply to Clive, to whom - thanks again for your help.
I thought I should understand more about the problem before tackling it. First I used Notepad ++ to establish the scale of the loss: 2770 bookmarks missing from 1344 files (“containers”) across 4 projects.
I then downloaded some XML editors to examine the .scrivx files, and realised I could adapt your suggestion of copying and pasting from within Scrivener to Microsoft XML Notepad. It is a simple matter to display the two .scrivx files next to each other as trees, search for each instance of the element in the old file, and then drag and drop each one across to the right place in the new file. This transfers all the bookmarks in that container in a single action. The imported elements then need to be renamed to conform to the new method described by AmberV above, and any duplicates merged.
It took me half a day to work out how XML works and set this up, and another half a day to fix one of my smallest projects. Once I was up and running, I repaired about 90 containers in an hour, by which time my eyes were so glazed over I had to go for a walk. I estimate that to fix all my projects it would take about 30 hours of continuous work, spread over at least 6 days. So: this is a solution, but still a painful one.
The good news is that the work process was simple and iterative, and should be reproduceable in software. Here is a sketch of a spec:
- The BAK file is my older Scrivener 1.9 XML back-up with the bookmarks in it.
- The LIVE file is my newer Scrivener 3 XML file.
-
Create a list of the missing bookmarks: BookMarkList.
From the start of the BAK file,
Find the next element (note the plural: References).
Export the whole element (with its children), together with the UUID attribute of its parent element.
Add it to the BookMarkList.
Repeat until the end of the BAK file. -
Import the missing bookmarks into the LIVE file.
For each item on the BookMarkList,
Find the element in the LIVE file with the matching UUID attribute.
Import the whole element into that . (Does the exact ordering of the elements matter? I don’t know - I reproduced the order as it was in the BAK file.) -
Update the element names.
In the LIVE file,
Replace ‘Reference’ with ‘Bookmark’ (not whole words only, so that the plural ‘References’ is replaced with ‘Bookmarks’)in the element names only (in case the word ‘refereence’ appears in a url or title). -
Merge any duplicate elements.
From the start of the LIVE file,
Find the next that contain two elements (note plural: Bookmarks).
Merge the two elements.
Repeat until the end of the LIVE file.
This step corrects any containers where the Scrivener update successfully transfered old internal references, and also where new references have been added since the update.
Isn’t that it? Would it really take several programmers more than a week to write that? I’d certainly be happy to help test it. It may be even simpler, if the import/update/merge operations were done on the fly, without creating an intermediate BookMarkList. But I find it clearer to explain it that way.
You mentioned that the nested structure of the XML file complicates this, but does it really, if approached in this way? And I can’t think of any scenarios where post-update edits to the LIVE file such as moving containers, adding text or metadata would trip this up. Maybe I’ve missed something.
I had a look at the scripting tools you mentioned to see if I might have a go at this myself, but sadly that is beyond me. I know a bit about logic, but not much about programming.
What do you think?