1

Тема: AHK: Сохранение древовидной структуры

На жёстком диске имеется папка, которая может содержать файлы, другие подпапки, те в свою очередь могут также хранить внутри себя файлы и подпапки и т. д. В общем, разветвлённая структура с большой степенью вложенности.

Хочется всё это дело пропарсить и иметь возможность держать в переменной (точнее в объекте), и сохранять в  xml-файл (в xml нажал плюсик - раскрывается ветка дерева).

Как из объекта сохранить в файл, я вроде придумал. Трудности возникли с тем, как сохранять в объект.

Root := {}

%A_LoopFile% := "Мои документы\Моя музыка\классика\Укупник.mp3"
Root["Мои документы", "Моя музыка", "классика"] := %A_LoopFile%

%A_LoopFile% := "Мои документы\Моя музыка\попса\кантри\Газманов.wav"
Root["Мои документы", "Моя музыка", "попса", "кантри"] := %A_LoopFile%

Сколько будет уровней, заранее неизвестно, поэтому сделать шаблон не удаётся. Какие есть идеи?

2 (изменено: teadrinker, 2019-10-24 21:41:30)

Re: AHK: Сохранение древовидной структуры

ypppu пишет:

Как из объекта сохранить в файл, я вроде придумал.

По-моему, объект здесь лишнее звено, если имеешь в виду объект {}. Рекурсивным обходом папок можно создать XML-файл, потом, если нужно получать информацию из этого файла, загружаем этот файл и работаем с объектом Xml Document. Его можно рекурсивно парсить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: Сохранение древовидной структуры

Собственно, и сам XML-файл может понадобиться только для того, чтобы сохранять предыдущие состояния файловой системы. Чтобы получать текущую информацию, проще сразу парсить саму файловую систему.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

4

Re: AHK: Сохранение древовидной структуры

Ясно, спасибо.
А как лучше парсить? Можно перебирать все файлы и папки от начала до конца, но не понятно как дать понять скрипту, какая папка (либо файл) в какую папку вложена?
Можно брать по порядку папки, расположенные внутри коревой папки, прочёсывать все подпапки и файлы. Надо будет как-то запоминать, в которой папке сейчас "находится" скрипт и какие папки уже были просмотрены. Что-то сложно получается.

5

Re: AHK: Сохранение древовидной структуры

Есть такое понятие, как рекурсивный обход. Пример создания XML из дерева папок:

#NoEnv
SetBatchLines, -1

CreateXmlFromFolder("D:\Downloads")

CreateXmlFromFolder(folder) {
   xmlDoc := ComObjCreate("Msxml2.DOMDocument.3.0")
   xmlDoc.async := false
   SplitPath, folder, fileName
   xmlDoc.loadXML("<folder name=""" . fileName . """></folder>")
   root := xmlDoc.documentElement
   Parse(xmlDoc, folder, root)
   xmlDoc.save(A_ScriptDir . "\test.xml")
}

Parse(xmlDoc, folder, node) {
   Loop, files, %folder%\*, D
   {
      newElem := xmlDoc.createElement("folder")
      node.appendChild(newElem)
      node.lastChild.setAttribute("name", A_LoopFileName)
      Parse(xmlDoc, A_LoopFilePath, node.lastChild)
   }
   Loop, files, %folder%\*, F
   {
      newElem := xmlDoc.createElement("file")
      node.appendChild(newElem)
      node.lastChild.setAttribute("name", A_LoopFileName)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

6 (изменено: teadrinker, 2019-10-25 04:55:42)

Re: AHK: Сохранение древовидной структуры

Нашёл, как отформатировать сразу:

#NoEnv
SetBatchLines, -1

CreateXmlFromFolder("D:\Downloads")

CreateXmlFromFolder(folder) {
   xmlDoc := ComObjCreate("Msxml2.DOMDocument.6.0")
   xmlDoc.async := false
   SplitPath, folder, fileName
   xmlDoc.loadXML("<folder name=""" . fileName . """></folder>")
   root := xmlDoc.documentElement
   Parse(xmlDoc, folder, root)
   FormatDocument(xmlDoc)
   xmlDoc.save(A_ScriptDir . "\test.xml")
}

Parse(xmlDoc, folder, node) {
   Loop, files, %folder%\*, D
   {
      newElem := xmlDoc.createElement("folder")
      newNode := node.appendChild(newElem)
      newNode.setAttribute("name", A_LoopFileName)
      Parse(xmlDoc, A_LoopFilePath, newNode)
   }
   Loop, files, %folder%\*, F
   {
      newElem := xmlDoc.createElement("file")
      newNode := node.appendChild(newElem)
      newNode.setAttribute("name", A_LoopFileName)
   }
}

FormatDocument(xmlDoc) {
   xmlReader := ComObjCreate("msxml2.SAXXMLReader.6.0")
   xmlWriter := ComObjCreate("msxml2.MXXMLWriter.6.0")
   xmlWriter.encoding := "UTF-8"
   xmlWriter.byteOrderMark := true
   xmlWriter.disableOutputEscaping := false
   xmlWriter.omitXMLDeclaration := false
   xmlWriter.indent := true
   xmlReader.contentHandler  := xmlWriter
   xmlReader.dtdHandler      := xmlWriter
   xmlReader.errorHandler    := xmlWriter
   xmlReader.putProperty("http://xml.org/sax/properties/lexical-handler", xmlWriter)
   xmlReader.putProperty("http://xml.org/sax/properties/declaration-handler", xmlWriter)
   xmlReader.parse(xmlDoc)
   xmlDoc.loadXML(xmlWriter.output)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7

Re: AHK: Сохранение древовидной структуры

Как можно получить содержимое xml-файла в переменную? То есть вместо сохранения в файл всё то же самое передать в переменную?

8

Re: AHK: Сохранение древовидной структуры

MsgBox, % xmlDoc.xml
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg