Documenting: LibreOffice Writer Template Changing

Internally, LibreOffice Writer has been used for technical documentation for many years:

  • Writer is very strong in combination with style sheets and
  • SVG format is perfectly supported. Vector-based images can therefore be inserted very well.

When you work with large documents, there is an annoying peculiarity you should be aware of: It is not possible to link templates to documents from the user interface. This sounds a bit crazy and yes, it may be considered to be a bug, a reason not to use LibreOffice.

An extension “Template Changer” was available for linking template files. However, it does not work with new versions. That is why we created a BASH script as a tool to solve this. It has been tested on Linux but should also work with Cygwin on Windows. OS-X should work with minor changes, like the date function in Unix does not require an @ sign.

The underlying idea is that you have documentation projects where both the documents and the templates are in the same directory. If that is the case with you, then this script can help you.

You can paste the following to a text file called “cht.sh”, give it executable rights, put it in your documentation directory,  and start attaching templates to your documents.

Hope you like it!

Update 2018-11-19: Now both ODT and ODM files are supported.
Update 2023: Repaginating bug is solved and information is removed from this page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/bin/bash
 
# Template CHanger alternative
# This script uses xmlstarlet, zip and unzip.
echo
echo ./cht.sh, CHange Template...
echo This script inserts or replaces, a template XML node in a 
echo LibreOffice Writer file, by modifying meta.xml and adding an
echo absolute url for template location. It accepts both
echo document and master document files and template files.
echo xmlstarlet is expected to be installed.
echo This is for documentation projects where Writer files and Templates
echo reside in the same directory!
echo USE AT YOUR OWN RISK, HAVE A BACK-UP READY, wiebe-nedcad-nl
echo Run script always in directory with documents, cd your_project
echo "Usage: cht <OTT-file> <ODT-or-ODM-file>"
echo Example: ./cht.sh template.ott writer.odt
echo
 
## Variables I, more below Checks
 
# General
TEMPL=$1
DOC=$2
WORKDIR="temp_extracted"
 
## Checks
 
# Do files exist with right extension?
 
if [ -f $TEMPL ] && [ "${TEMPL: -4}" == ".ott" ]; then
   echo "File $TEMPL found."
else
   echo "ERROR: Writer template $TEMPL does not exist or is not valid. Aborting."
   exit 1
fi
 
if [ -f $DOC ] && ([ "${DOC: -4}" == ".odt" ] || [ "${DOC: -4}" == ".odm" ]); then
   echo "File $DOC found."
else
   echo "ERROR: Writer document $DOC does not exist or is not valid. Aborting."
   exit 1
fi
 
# Do we have xmlstarlet?
 
hash xmlstarlet 2>/dev/null || { echo >&2 "ERROR: xmlstarlet is required. Please install this first. Aborting."; exit 1; }
 
## Variables II
 
# XML node "meta:template" values
echo Node meta:template will contain the following bare attributes:
# xlink:type xlink:actuate xlink:title xlink:href meta:date
 
# Static
N_XLINK_TYPE="xlink:type" && V_XLINK_TYPE="simple"
echo $N_XLINK_TYPE -- $V_XLINK_TYPE
 
# Static
N_XLINK_ACTUATE="xlink:actuate" && V_XLINK_ACTUATE="onRequest"
echo $N_XLINK_ACTUATE -- $V_XLINK_ACTUATE
 
# Template name
N_XLINK_TITLE="xlink:title"
NO_EXT="${TEMPL%.*}"
V_XLINK_TITLE=${NO_EXT##*/}
echo $N_XLINK_TITLE -- $V_XLINK_TITLE
 
# Absolute template location
N_XLINK_HREF="xlink:href"
V_XLINK_HREF="$PWD/$TEMPL"
echo $N_XLINK_HREF -- $V_XLINK_HREF
 
# Template time
N_META_DATE="meta:date"
# Lower epoch time sec to force updating document styles
BELLE_EPOCH_COR=-1
BELLE_EPOCH_X=$(stat -c %Y $TEMPL)
BELLE_EPOCH=$((BELLE_EPOCH_X+BELLE_EPOCH_COR))
V_META_DATE=$(date -d @$BELLE_EPOCH +%Y-%m-%dT%T.%9N)
echo $N_META_DATE -- $V_META_DATE
echo
 
## The proces
 
# Unzip the document file
 
mkdir -p $WORKDIR
if [ -z "$(ls -A ./$WORKDIR)" ]; then
   echo "Ready for processing meta.xml"
else
   echo "ERROR: ./$WORKDIR is not empty and may contain an unzipped document file. Aborting."
   exit 1
fi
unzip -q $DOC -d $WORKDIR
cd $WORKDIR
 
# If exists, delete node meta:template, add node and subnodes via pipes
xmlstarlet ed -d "/office:document-meta/office:meta/meta:template" meta.xml | \
xmlstarlet ed -s  "/office:document-meta/office:meta" -t elem -n meta:template | \
xmlstarlet ed -i  "/office:document-meta/office:meta/meta:template" -t attr -n $N_XLINK_TYPE -v $V_XLINK_TYPE | \
xmlstarlet ed -i  "/office:document-meta/office:meta/meta:template" -t attr -n $N_XLINK_ACTUATE -v $V_XLINK_ACTUATE | \
xmlstarlet ed -i  "/office:document-meta/office:meta/meta:template" -t attr -n $N_XLINK_TITLE -v $V_XLINK_TITLE | \
xmlstarlet ed -i  "/office:document-meta/office:meta/meta:template" -t attr -n $N_XLINK_HREF -v $V_XLINK_HREF | \
xmlstarlet ed -i  "/office:document-meta/office:meta/meta:template" -t attr -n $N_META_DATE -v $V_META_DATE \
> temp.xml && mv temp.xml meta.xml
 
# What is the result?
echo meta.xml is now: && echo
cat meta.xml && echo
 
# Back-up original file
mv ../$DOC "../${DOC%.*}.bak"
echo A .bak file is created && echo
 
# Create modified Writer file, mimetype first
zip -rq ../$DOC mimetype .
 
# Cleaning up
cd ..
rm -rf $WORKDIR
echo Finished && echo

Leave a comment