Запись не-ascii-символов в xml/UTF-8

У меня есть скрипт, который собирает XML-документ с помощью манипуляций со строками (который я написал до того, как открыл для себя XML Suite).

Когда включены определенные символы, такие как £, -(en-dash) и -(длинное тире) (я подозреваю, что все символы, отличные от ascii), они заменяются символом замены Unicode (U+FFFD).

Это только происходит, когда в начале документа есть заголовок xml: например, <?xml. Внесение любых изменений в это устраняет проблему и записывает в файл то, что я ожидал. Я предполагаю, что applescript пытается проанализировать строку как xml, но я хочу, чтобы она прошла как строка.

Я пишу в JXA, но включил эквивалент Applescript, так как я думаю, что проблема связана с OSA, и, вероятно, пользователей AppleScript больше!

редактировать: хорошо, я думаю, это больше проблема с кодировкой - чтение как UTF-8 (которым должен быть xml, который я генерирую) приводит к замене символа, но Western или Mac Roman правильно отображают символы. UTF-8 определенно поддерживает эти символы, поэтому я не уверен, что это лучший способ двигаться вперед?

edit 2: Просто чтобы прояснить: я думаю, что происходит то, что символы, отличные от ascii, кодируются чем-то другим, кроме UTF-8, что делает мой вывод XML недействительным. Как я могу заставить applescript или JXA кодировать символы, отличные от ascii, как UTF-8?

Эпплскрипт

set dt to path to desktop as text
set filePath to dt & "test1.txt"

writeTextToFile(text1, filePath, true)

-- using the example handler from the Mac Automation Scripting Guide
on writeTextToFile(theText, theFile, overwriteExistingContent)
    try

        -- Convert the file to a string
        set theFile to theFile as string

        -- Open the file for writing
        set theOpenedFile to open for access file theFile with write permission

        -- Clear the file if content should be overwritten
        if overwriteExistingContent is true then set eof of theOpenedFile to 0

        -- Write the new content to the file
        write theText to theOpenedFile starting at eof

        -- Close the file
        close access theOpenedFile

        -- Return a boolean indicating that writing was successful
        return true

        -- Handle a write error
    on error

        -- Close the file
        try
            close access file theFile
        end try

        -- Return a boolean indicating that writing failed
        return false
    end try
end writeTextToFile

Javascript для автоматизации

app.includeStandardAdditions = true

function writeTextToFile(text, file, overwriteExistingContent) {
    try {

        // Convert the file to a string
        var fileString = file.toString()

        // Open the file for writing
        var openedFile = app.openForAccess(Path(fileString), { writePermission: true })

        // Clear the file if content should be overwritten
        if (overwriteExistingContent) {
            app.setEof(openedFile, { to: 0 })
        }

        // Write the new content to the file
        app.write(text, { to: openedFile, startingAt: app.getEof(openedFile) })

        // Close the file
        app.closeAccess(openedFile)

        // Return a boolean indicating that writing was successful
        return true
    }
    catch(error) {

        try {
            // Close the file
            app.closeAccess(file)
        }
        catch(error) {
            // Report the error is closing failed
            console.log(`Couldn't close file: ${error}`)
        }

        // Return a boolean indicating that writing was successful
        return false
    }
}

var text = "<?xml £"
var file = Path("Users/benfrearson/Desktop/text.txt")


writeTextToFile (text, file, true)

person Ben Frearson    schedule 19.05.2020    source источник
comment
Учитывая ваш код AppleScript, какое значение предполагается присвоить переменной text1, чтобы воспроизвести вашу проблему? Это должно быть set text1 to "<?xml £" ? Потому что, когда я добавляю эту строку кода и запускаю ваш AppleScript, он записывает на Рабочий стол новый файл с именем test1.txt. Если я затем открою этот результирующий файл, например. TextEdit имеет следующее содержимое: <?xml £ - Вы говорите, что это не то, что происходит для вас, и вместо этого содержимое имеет юникод?   -  person RobC    schedule 19.05.2020
comment
Упс, да! похоже, я пропустил верхнюю строчку! Когда я явно открываю его (в Atom) и устанавливаю кодировку UTF-8, он не отображает символ £.   -  person Ben Frearson    schedule 20.05.2020
comment
Отвечает ли это на ваш вопрос? Как я могу писать файлы UTF-8 используете JavaScript для автоматизации Mac?   -  person RobC    schedule 20.05.2020


Ответы (1)


В AppleScript вы бы использовали write theText to theFile as «class utf8» для записи текста в кодировке UTF8. Вы не можете сделать это в JXA, так как нет возможности писать необработанные коды AE.

Обычно я не рекомендую JXA, так как он 1. глючный и ущербный, и 2. заброшенный. Если вам нравится JavaScript в целом, вам гораздо лучше подойдет Node. Для автоматизации приложений вам лучше всего придерживаться AppleScript: хотя это дрянной язык, а также умирающий, по крайней мере, он правильно говорит о событиях Apple и имеет приличную документацию и поддержку сообщества.

Если вы должны использовать JXA, единственным обходным путем является запись файла UTF8 через API Cocoa. Хотя генерация XML с помощью затирания строк в любом случае является злом и подвержена ошибкам, вы, вероятно, воспользуетесь возможностью переписать свой код, чтобы использовать правильный XML API. (Опять же, с Node вы избалованы выбором, и самой сложной частью будет выяснить, какие библиотеки NPM надежны и просты в использовании, а какие — мусор. С AS/JXA это либо пакет XML System Events, который медленный, либо XML API Cocoa, которые сложны.)

person foo    schedule 19.05.2020
comment
Да, это ответ на вопрос! Работает в Applescript, без шансов в чистом JXA. Я нашел больше информации здесь. Я выбрал JXA, потому что мне нужно было делать дополнительные манипуляции со строками, о которых AppleScript так туп. Чтобы было ясно: я читаю файл шаблона XML, а затем заменяю строку-заполнитель значениями из текстового файла. Вероятно, в будущем лучше использовать XML API (но пока это надежно) - person Ben Frearson; 20.05.2020