Hi. I’m using Applescript to create an XML file and so need to save it as text-only. While the resulting file appears to be a text-only file, it will not work. If I manually copy all the text into, say, a Word document and save that as text-only it does work. Obviously, I’m writing the file incorrectly. What is the correct way to do this? Here’s the part of my code that writes the file:
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
if append_data is false then ¬
set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof as «class utf8»
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
Thanks, Michael
Hi Michael,
this is just the subroutine.
It’s more interesting how you call the routine and pass the parameters
Hi Stefan. Here’s the whole script (actually, you helped me with this one in a previous post)
property searchList : {" "}
property replaceList : {"_"}
--Set these variables
set thesePlaylists to {"Playlist 1", "Playlist 2", "Playlist 3", "Playlist 4", "Playlist 5"}
set lo_res_folder to "mp3_lo/"
set hi_res_folder to "mp3_hi/"
set aif_folder to "aif/"
set this_data to ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" & return as string) & return as string
set myFileName to "library.xml"
--end set these variables
set new_track_genre to ""
set new_track_subgenre to ""
set this_file to ((path to desktop folder as Unicode text) & myFileName)
my write_to_file(this_data, this_file, true)
repeat with thisPlaylist in thesePlaylists
tell application "iTunes"
file tracks of user playlist thisPlaylist
repeat with thisTrack in result
set track_name_c to my convertText(name of thisTrack)
set track_name to name of thisTrack
set track_genre to new_track_genre
set new_track_genre to grouping of thisTrack
set track_subgenre to new_track_subgenre
set new_track_subgenre to genre of thisTrack
set no_seconds to duration of thisTrack as number
set no_minutes to no_seconds div 60
set no_seconds to round (no_seconds mod 60)
if no_seconds < 10 then
set seconds_text to "0" & (no_seconds as string)
else
set seconds_text to no_seconds as string
end if
set trackDuration to (no_minutes as string) & ":" & seconds_text
--write to TEXT file
if new_track_genre = track_genre then
if new_track_subgenre = track_subgenre then
set this_data to tab & tab & "<track duration=\"" & trackDuration & "\" lo_res=\"" & lo_res_folder & track_name_c & "_lo.mp3\"" & " hi_res=\"" & hi_res_folder & track_name_c & ".mp3\"" & " aiff=\"" & aif_folder & track_name_c & ".aif\">" & track_name & "</track>" & return as string
else
set this_data to tab & "</subgenre>" & return & tab & "<subgenre title=\"" & new_track_subgenre & "\">" & return & tab & tab & "<track duration=\"" & trackDuration & "\" lo_res=\"" & lo_res_folder & track_name_c & "_lo.mp3\"" & " hi_res=\"" & hi_res_folder & track_name_c & ".mp3\"" & " aiff=\"" & aif_folder & track_name_c & ".aif\">" & track_name & "</track>" & return as string
end if
else
if track_genre = "" then
set this_data to "<genre title=\"" & new_track_genre & "\">" & return & tab & "<subgenre title=\"" & new_track_subgenre & "\">" & return & tab & tab & "<track duration=\"" & trackDuration & "\" lo_res=\"" & lo_res_folder & track_name_c & "_lo.mp3\"" & " hi_res=\"" & hi_res_folder & track_name_c & ".mp3\"" & " aiff=\"" & aif_folder & track_name_c & ".aif\">" & track_name & "</track>" & return as string
else
set this_data to tab & "</subgenre>" & return & "</genre>" & return & return & "<genre title=\"" & new_track_genre & "\">" & return & tab & "<subgenre title=\"" & new_track_subgenre & "\">" & return & tab & tab & "<track duration=\"" & trackDuration & "\" lo_res=\"" & lo_res_folder & track_name_c & "_lo.mp3\"" & " hi_res=\"" & hi_res_folder & track_name_c & ".mp3\"" & " aiff=\"" & aif_folder & track_name_c & ".aif\">" & track_name & "</track>" & return as string
end if
end if
set this_file to ((path to desktop folder as Unicode text) & myFileName)
my write_to_file(this_data, this_file, true)
end repeat
end tell
end repeat
set this_data to tab & "</subgenre>" & return & "</genre>" as string
set this_file to ((path to desktop folder as Unicode text) & myFileName)
my write_to_file(this_data, this_file, true)
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
if append_data is false then ¬
set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof as «class utf8»
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
to switchText of t from s to r
set text item delimiters to s
set t to t's text items
set text item delimiters to r
tell t to set t to beginning & ({""} & rest)
t
end switchText
to convertText(t)
set d to text item delimiters
considering case
repeat with n from 1 to count searchList
set t to switchText of t from my searchList's item n to my replaceList's item n
end repeat
end considering
set text item delimiters to d
t
end convertText
display dialog "Finished!" buttons {"Okay"} default button 1 with icon 1
I would prefer to concatenate all the data to one string and write finally the data to disk
btw:
Once defined as class string, you can (and should) omit all as-string-coercions later, because
AppleScript will take the class of the first text element and will coerce while concatenting the following ones automatically
The default text class is string, so this is sufficient for the header
set this_data to "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" & return & return
Explain “will not work”.
My first guess was the carriage returns (ASCII character 13); I would expect line feeds (ASCII character 10) to be the proper character for an XML file. A quick check shows that Word is changing the returns to line feeds, so I believe that’s your (main*) problem.
I would add this near the top of your script:
-- Use a variable for line feeds so you only have to call `ASCII character` once
set lineFeed to ASCII character 10
Then replace all the (textual!) returns in your script with that variable.
- Take out the needless
as string
coercions that Stefan pointed out.
Thanks Bruce & Stefan. Changing the returns worked. I made the other suggested changes as well.
Michael